2021-01-06 12:17:17 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
Created on Fri Dec 25 21:25:14 2020
|
|
|
|
|
|
|
|
@author: DJ2LS
|
|
|
|
"""
|
|
|
|
|
|
|
|
import time
|
|
|
|
import logging
|
2021-03-04 13:28:01 +00:00
|
|
|
import asyncio
|
2021-03-12 13:14:36 +00:00
|
|
|
import crcengine
|
2021-01-06 12:17:17 +00:00
|
|
|
|
2021-02-28 15:46:18 +00:00
|
|
|
|
2021-01-06 12:17:17 +00:00
|
|
|
import static
|
2021-03-12 15:18:41 +00:00
|
|
|
import data_handler
|
2021-01-06 12:17:17 +00:00
|
|
|
|
2021-08-15 10:34:28 +00:00
|
|
|
def wait(seconds):
|
2021-08-14 18:00:32 +00:00
|
|
|
timeout = time.time() + seconds
|
|
|
|
|
|
|
|
while time.time() < timeout:
|
|
|
|
time.sleep(0.01)
|
|
|
|
|
|
|
|
|
2021-02-10 18:43:59 +00:00
|
|
|
|
2021-01-06 12:17:17 +00:00
|
|
|
def get_crc_8(data):
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
Get the CRC8 of a byte string
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
param: data = bytes()
|
|
|
|
"""
|
2021-03-12 13:14:36 +00:00
|
|
|
crc_algorithm = crcengine.new('crc8-ccitt') # load crc8 library
|
2021-01-06 12:17:17 +00:00
|
|
|
crc_data = crc_algorithm(data)
|
2021-03-12 13:14:36 +00:00
|
|
|
crc_data = crc_data.to_bytes(1, byteorder='big')
|
2021-01-06 12:17:17 +00:00
|
|
|
return crc_data
|
|
|
|
|
2021-03-12 13:14:36 +00:00
|
|
|
|
2021-01-06 12:17:17 +00:00
|
|
|
def get_crc_16(data):
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
Get the CRC16 of a byte string
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
param: data = bytes()
|
|
|
|
"""
|
2021-03-12 13:14:36 +00:00
|
|
|
crc_algorithm = crcengine.new('crc16-ccitt-false') # load crc16 library
|
2021-01-06 12:17:17 +00:00
|
|
|
crc_data = crc_algorithm(data)
|
2021-03-12 13:14:36 +00:00
|
|
|
crc_data = crc_data.to_bytes(2, byteorder='big')
|
|
|
|
return crc_data
|
|
|
|
|
2021-03-12 15:18:41 +00:00
|
|
|
def watchdog():
|
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
|
|
|
|
|
|
|
watchdog master function. Frome here we call the watchdogs
|
|
|
|
"""
|
|
|
|
while True:
|
|
|
|
time.sleep(0.01)
|
|
|
|
data_channel_keep_alive_watchdog()
|
|
|
|
|
|
|
|
def data_channel_keep_alive_watchdog():
|
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
2021-03-16 09:55:48 +00:00
|
|
|
if static.ARQ_STATE == 'DATA' and static.TNC_STATE == 'BUSY': # and not static.ARQ_SEND_KEEP_ALIVE:
|
2021-03-12 15:18:41 +00:00
|
|
|
time.sleep(0.01)
|
2021-03-16 10:39:22 +00:00
|
|
|
if static.ARQ_DATA_CHANNEL_LAST_RECEIVED + 30 > time.time():
|
2021-03-16 09:55:48 +00:00
|
|
|
pass
|
2021-03-12 15:18:41 +00:00
|
|
|
else:
|
|
|
|
static.ARQ_DATA_CHANNEL_LAST_RECEIVED = 0
|
2021-03-16 10:39:22 +00:00
|
|
|
logging.info("DATA [" + str(static.MYCALLSIGN, 'utf-8') + "]<<T>>[" + str(static.DXCALLSIGN, 'utf-8') + "] [BER." + str(static.BER) + "]")
|
2021-03-12 15:18:41 +00:00
|
|
|
arq_reset_frame_machine()
|
2021-03-04 13:28:01 +00:00
|
|
|
|
2021-03-12 13:14:36 +00:00
|
|
|
|
2021-02-10 14:04:18 +00:00
|
|
|
def arq_reset_timeout(state):
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
|
|
|
"""
|
2021-02-10 14:04:18 +00:00
|
|
|
static.ARQ_RX_ACK_TIMEOUT = state
|
|
|
|
static.ARQ_RX_FRAME_TIMEOUT = state
|
|
|
|
static.ARQ_RX_RPT_TIMEOUT = state
|
2021-03-12 13:14:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
def arq_reset_ack(state):
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
|
|
|
"""
|
2021-02-10 14:04:18 +00:00
|
|
|
static.ARQ_ACK_RECEIVED = state
|
|
|
|
static.ARQ_RPT_RECEIVED = state
|
|
|
|
static.ARQ_FRAME_ACK_RECEIVED = state
|
2021-03-12 13:14:36 +00:00
|
|
|
|
|
|
|
|
2021-02-10 14:04:18 +00:00
|
|
|
def arq_reset_frame_machine():
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
Reset the frame machine parameters to default,
|
|
|
|
so we need to call just a function
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
2021-02-10 14:04:18 +00:00
|
|
|
arq_reset_timeout(False)
|
|
|
|
arq_reset_ack(False)
|
|
|
|
static.TX_N_RETRIES = 0
|
|
|
|
static.ARQ_N_SENT_FRAMES = 0
|
|
|
|
static.ARQ_TX_N_FRAMES_PER_BURST = 0
|
2021-03-10 08:12:49 +00:00
|
|
|
static.ARQ_TX_N_CURRENT_ARQ_FRAME = 0
|
|
|
|
static.ARQ_TX_N_TOTAL_ARQ_FRAMES = 0
|
|
|
|
static.ARQ_TX_N_CURRENT_ARQ_FRAME = 0
|
2021-03-12 13:14:36 +00:00
|
|
|
|
2021-03-10 08:12:49 +00:00
|
|
|
static.ARQ_RX_N_CURRENT_ARQ_FRAME = 0
|
|
|
|
static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME = 0
|
|
|
|
static.ARQ_FRAME_BOF_RECEIVED = False
|
2021-03-12 13:14:36 +00:00
|
|
|
static.ARQ_FRAME_EOF_RECEIVED = False
|
2021-03-16 09:55:48 +00:00
|
|
|
|
|
|
|
static.ARQ_RX_BURST_BUFFER = []
|
|
|
|
static.ARQ_RX_FRAME_BUFFER = []
|
|
|
|
|
2021-03-12 13:14:36 +00:00
|
|
|
static.TNC_STATE = 'IDLE'
|
2021-03-16 09:55:48 +00:00
|
|
|
static.ARQ_STATE = 'IDLE'
|
|
|
|
###static.ARQ_CONNECTION_KEEP_ALIVE_RECEIVED = int(time.time()) # we need to reset the counter at this point
|
|
|
|
###static.ARQ_SEND_KEEP_ALIVE = True
|
2021-03-04 13:28:01 +00:00
|
|
|
static.CHANNEL_STATE = 'RECEIVING_SIGNALLING'
|
|
|
|
static.ARQ_READY_FOR_DATA = False
|
2021-03-12 13:14:36 +00:00
|
|
|
|
2021-03-18 10:39:12 +00:00
|
|
|
static.ARQ_START_OF_TRANSMISSION = 0
|
|
|
|
|
|
|
|
def calculate_transfer_rate():
|
2021-09-11 07:21:22 +00:00
|
|
|
if static.ARQ_START_OF_TRANSMISSION > 0:
|
|
|
|
static.TOTAL_TRANSMISSION_TIME = time.time() - static.ARQ_START_OF_TRANSMISSION
|
2021-08-23 16:38:26 +00:00
|
|
|
|
2021-09-06 18:31:12 +00:00
|
|
|
|
|
|
|
print("ARQ_N_ARQ_FRAMES_PER_DATA_FRAME " + str(static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME))
|
|
|
|
print("ARQ_RX_N_CURRENT_ARQ_FRAME " + str(static.ARQ_RX_N_CURRENT_ARQ_FRAME))
|
|
|
|
|
2021-08-23 16:38:26 +00:00
|
|
|
|
|
|
|
|
2021-08-15 10:34:28 +00:00
|
|
|
arq_n_arq_frames_per_data_frame = static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME
|
2021-08-23 16:38:26 +00:00
|
|
|
arq_rx_n_current_arq_frame = static.ARQ_RX_N_CURRENT_ARQ_FRAME
|
2021-08-15 10:34:28 +00:00
|
|
|
|
2021-09-06 18:31:12 +00:00
|
|
|
if static.TX_BUFFER_SIZE == 0:
|
2021-08-15 10:34:28 +00:00
|
|
|
total_n_frames = arq_n_arq_frames_per_data_frame
|
|
|
|
elif arq_n_arq_frames_per_data_frame == 0:
|
2021-09-06 18:31:12 +00:00
|
|
|
total_n_frames = static.TX_BUFFER_SIZE
|
2021-08-15 10:34:28 +00:00
|
|
|
else:
|
|
|
|
total_n_frames = 0
|
2021-09-06 18:31:12 +00:00
|
|
|
|
2021-09-11 07:21:22 +00:00
|
|
|
if static.TOTAL_TRANSMISSION_TIME > 0:
|
|
|
|
#total_transmission_time = time.time() - static.ARQ_START_OF_TRANSMISSION
|
|
|
|
total_transmission_time = static.TOTAL_TRANSMISSION_TIME
|
|
|
|
print("total_transmission_time: " + str(total_transmission_time))
|
|
|
|
print("static.TOTAL_BYTES: " + str(static.TOTAL_BYTES))
|
2021-03-18 10:39:12 +00:00
|
|
|
|
|
|
|
|
2021-09-11 07:21:22 +00:00
|
|
|
|
|
|
|
static.ARQ_BITS_PER_SECOND = int((static.TOTAL_BYTES * 8) / total_transmission_time)
|
|
|
|
static.ARQ_BYTES_PER_MINUTE = int(((static.TOTAL_BYTES) / total_transmission_time) * 60)
|
|
|
|
|
|
|
|
burst_bytes = static.ARQ_PAYLOAD_PER_FRAME * static.ARQ_N_RX_FRAMES_PER_BURSTS
|
|
|
|
burst_transmission_time = time.time() - static.ARQ_START_OF_BURST
|
|
|
|
print("BURST TRANSMISSION TIME: " + str(burst_transmission_time))
|
|
|
|
static.ARQ_BITS_PER_SECOND_BURST = int((burst_bytes * 8) / burst_transmission_time)
|
|
|
|
static.ARQ_BYTES_PER_MINUTE_BURST = int(((burst_bytes) / burst_transmission_time) * 60)
|
|
|
|
print("static.ARQ_BITS_PER_SECOND_BURST: " + str(static.ARQ_BITS_PER_SECOND_BURST))
|
|
|
|
print("static.ARQ_BYTES_PER_MINUTE_BURST: " + str(static.ARQ_BYTES_PER_MINUTE_BURST))
|
2021-08-14 18:00:32 +00:00
|
|
|
|
2021-09-11 07:21:22 +00:00
|
|
|
# PERCENTAGE FOR TRANSMITTING
|
2021-09-06 18:31:12 +00:00
|
|
|
if static.TX_BUFFER_SIZE > 0:
|
2021-09-11 07:41:37 +00:00
|
|
|
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)
|
2021-08-15 10:34:28 +00:00
|
|
|
|
2021-09-11 07:21:22 +00:00
|
|
|
# PERCENTAGE FOR RECEIVING
|
2021-08-15 10:34:28 +00:00
|
|
|
elif arq_n_arq_frames_per_data_frame > 0:
|
2021-09-11 07:21:22 +00:00
|
|
|
static.ARQ_TRANSMISSION_PERCENT = int((static.ARQ_RX_N_CURRENT_ARQ_FRAME / static.ARQ_N_ARQ_FRAMES_PER_DATA_FRAME) * 100)
|
|
|
|
|
2021-08-14 18:00:32 +00:00
|
|
|
else:
|
|
|
|
static.ARQ_TRANSMISSION_PERCENT = 0.0
|
2021-03-18 10:39:12 +00:00
|
|
|
|
2021-09-11 07:21:22 +00:00
|
|
|
print("static.ARQ_TRANSMISSION_PERCENT: " + str(static.ARQ_TRANSMISSION_PERCENT))
|
|
|
|
print("static.ARQ_BYTES_PER_MINUTE: " + str(static.ARQ_BYTES_PER_MINUTE))
|
|
|
|
print("static.ARQ_BITS_PER_SECOND: " + str(static.ARQ_BITS_PER_SECOND))
|
2021-08-14 18:00:32 +00:00
|
|
|
return [static.ARQ_BITS_PER_SECOND, static.ARQ_BYTES_PER_MINUTE, static.ARQ_BITS_PER_SECOND_BURST, static.ARQ_BYTES_PER_MINUTE_BURST]
|
2021-08-22 14:59:32 +00:00
|
|
|
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-07-28 16:43:41 +00:00
|
|
|
def add_to_heard_stations(dxcallsign,dxgrid, datatype, snr):
|
2021-03-16 14:21:58 +00:00
|
|
|
# check if buffer empty
|
|
|
|
if len(static.HEARD_STATIONS) == 0:
|
2021-07-28 16:43:41 +00:00
|
|
|
static.HEARD_STATIONS.append([dxcallsign,dxgrid, int(time.time()), datatype, snr])
|
2021-03-16 14:21:58 +00:00
|
|
|
# if not, we search and update
|
|
|
|
else:
|
|
|
|
for i in range(0, len(static.HEARD_STATIONS)):
|
|
|
|
# update callsign with new timestamp
|
|
|
|
if static.HEARD_STATIONS[i].count(dxcallsign) > 0:
|
2021-07-28 16:43:41 +00:00
|
|
|
static.HEARD_STATIONS[i] = [dxcallsign,dxgrid, int(time.time()), datatype, snr]
|
2021-03-16 14:21:58 +00:00
|
|
|
break
|
|
|
|
# insert if nothing found
|
|
|
|
if i == len(static.HEARD_STATIONS) - 1:
|
2021-07-28 16:43:41 +00:00
|
|
|
static.HEARD_STATIONS.append([dxcallsign,dxgrid, int(time.time()), datatype, snr])
|
2021-03-16 14:21:58 +00:00
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
# for idx, item in enumerate(static.HEARD_STATIONS):
|
|
|
|
# if dxcallsign in item:
|
|
|
|
# item = [dxcallsign, int(time.time())]
|
|
|
|
# static.HEARD_STATIONS[idx] = item
|
|
|
|
|
2021-02-16 13:23:57 +00:00
|
|
|
def setup_logging():
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
|
|
|
Author: DJ2LS
|
2021-03-12 15:18:41 +00:00
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
Set the custom logging format so we can use colors
|
2021-03-16 09:55:48 +00:00
|
|
|
|
|
|
|
# https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output
|
|
|
|
# 'DEBUG' : 37, # white
|
|
|
|
# 'INFO' : 36, # cyan
|
|
|
|
# 'WARNING' : 33, # yellow
|
|
|
|
# 'ERROR' : 31, # red
|
|
|
|
# 'CRITICAL': 41, # white on red bg
|
|
|
|
|
2021-03-12 13:39:36 +00:00
|
|
|
"""
|
2021-03-12 13:14:36 +00:00
|
|
|
|
2021-09-10 15:59:01 +00:00
|
|
|
logging.basicConfig(level=logging.INFO, \
|
|
|
|
encoding='utf-8', \
|
|
|
|
format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', \
|
|
|
|
datefmt='%H:%M:%S', \
|
|
|
|
handlers=[logging.FileHandler("codec2-FreeDATA-TNC.log"),logging.StreamHandler()]
|
|
|
|
)
|
2021-02-16 13:23:57 +00:00
|
|
|
|
2021-03-12 13:14:36 +00:00
|
|
|
logging.addLevelName(logging.DEBUG, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.DEBUG))
|
|
|
|
logging.addLevelName(logging.INFO, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.INFO))
|
|
|
|
logging.addLevelName(logging.WARNING, "\033[1;33m%s\033[1;0m" % logging.getLevelName(logging.WARNING))
|
|
|
|
logging.addLevelName(logging.ERROR, "\033[1;31m%s\033[1;0m" % "FAILED")
|
2021-02-16 13:23:57 +00:00
|
|
|
#logging.addLevelName( logging.ERROR, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.ERROR))
|
2021-03-12 13:14:36 +00:00
|
|
|
logging.addLevelName(logging.CRITICAL, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.CRITICAL))
|
2021-02-16 13:23:57 +00:00
|
|
|
|
2021-03-12 13:14:36 +00:00
|
|
|
logging.addLevelName(25, "\033[1;32m%s\033[1;0m" % "SUCCESS")
|
|
|
|
logging.addLevelName(24, "\033[1;34m%s\033[1;0m" % "DATA")
|
2021-02-16 13:23:57 +00:00
|
|
|
|
2021-03-16 09:55:48 +00:00
|
|
|
|