mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Remove excess trailing spaces.
This commit is contained in:
parent
f2ef3f7ea2
commit
9753735c40
14 changed files with 978 additions and 945 deletions
18
tnc/audio.py
18
tnc/audio.py
|
@ -9,11 +9,11 @@ atexit.register(sd._terminate)
|
||||||
|
|
||||||
def get_audio_devices():
|
def get_audio_devices():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return list of input and output audio devices in own process to avoid crashes of portaudio on raspberry pi
|
return list of input and output audio devices in own process to avoid crashes of portaudio on raspberry pi
|
||||||
|
|
||||||
also uses a process data manager
|
also uses a process data manager
|
||||||
"""
|
"""
|
||||||
# we need to run this on windows for multiprocessing support
|
# we need to run this on windows for multiprocessing support
|
||||||
|
@ -24,22 +24,22 @@ def get_audio_devices():
|
||||||
# If we are not doing this at this early point, not all devices will be displayed
|
# If we are not doing this at this early point, not all devices will be displayed
|
||||||
sd._terminate()
|
sd._terminate()
|
||||||
sd._initialize()
|
sd._initialize()
|
||||||
|
|
||||||
with multiprocessing.Manager() as manager:
|
with multiprocessing.Manager() as manager:
|
||||||
|
|
||||||
proxy_input_devices = manager.list()
|
proxy_input_devices = manager.list()
|
||||||
proxy_output_devices = manager.list()
|
proxy_output_devices = manager.list()
|
||||||
#print(multiprocessing.get_start_method())
|
#print(multiprocessing.get_start_method())
|
||||||
p = multiprocessing.Process(target=fetch_audio_devices, args=(proxy_input_devices, proxy_output_devices))
|
p = multiprocessing.Process(target=fetch_audio_devices, args=(proxy_input_devices, proxy_output_devices))
|
||||||
p.start()
|
p.start()
|
||||||
p.join()
|
p.join()
|
||||||
|
|
||||||
return list(proxy_input_devices), list(proxy_output_devices)
|
return list(proxy_input_devices), list(proxy_output_devices)
|
||||||
|
|
||||||
def fetch_audio_devices(input_devices, output_devices):
|
def fetch_audio_devices(input_devices, output_devices):
|
||||||
"""
|
"""
|
||||||
get audio devices from portaudio
|
get audio devices from portaudio
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_devices: proxy variable for input devices
|
input_devices: proxy variable for input devices
|
||||||
output_devices: proxy variable for outout devices
|
output_devices: proxy variable for outout devices
|
||||||
|
@ -47,7 +47,7 @@ def fetch_audio_devices(input_devices, output_devices):
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
devices = sd.query_devices(device=None, kind=None)
|
devices = sd.query_devices(device=None, kind=None)
|
||||||
index = 0
|
index = 0
|
||||||
for device in devices:
|
for device in devices:
|
||||||
|
@ -55,7 +55,7 @@ def fetch_audio_devices(input_devices, output_devices):
|
||||||
# we need to do a try exception, beacuse for windows theres no audio device range
|
# we need to do a try exception, beacuse for windows theres no audio device range
|
||||||
try:
|
try:
|
||||||
name = device["name"]
|
name = device["name"]
|
||||||
|
|
||||||
maxOutputChannels = device["max_output_channels"]
|
maxOutputChannels = device["max_output_channels"]
|
||||||
maxInputChannels = device["max_input_channels"]
|
maxInputChannels = device["max_input_channels"]
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ def freedv_get_mode_value_by_name(mode):
|
||||||
"""
|
"""
|
||||||
get the codec2 mode by entering its string
|
get the codec2 mode by entering its string
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
|
|
||||||
Returns: int
|
Returns: int
|
||||||
|
|
||||||
|
@ -42,14 +42,14 @@ def freedv_get_mode_name_by_value(mode):
|
||||||
"""
|
"""
|
||||||
get the codec2 mode name as string
|
get the codec2 mode name as string
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
|
|
||||||
Returns: string
|
Returns: string
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return FREEDV_MODE(mode).name
|
return FREEDV_MODE(mode).name
|
||||||
|
|
||||||
|
|
||||||
# check if we are running in a pyinstaller environment
|
# check if we are running in a pyinstaller environment
|
||||||
try:
|
try:
|
||||||
app_path = sys._MEIPASS
|
app_path = sys._MEIPASS
|
||||||
|
@ -63,12 +63,12 @@ if sys.platform == 'linux':
|
||||||
files.append('libcodec2.so')
|
files.append('libcodec2.so')
|
||||||
elif sys.platform == 'darwin':
|
elif sys.platform == 'darwin':
|
||||||
files = glob.glob('**/*libcodec2*.dylib',recursive=True)
|
files = glob.glob('**/*libcodec2*.dylib',recursive=True)
|
||||||
|
|
||||||
elif sys.platform == 'win32' or sys.platform == 'win64':
|
elif sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
files = glob.glob('**\*libcodec2*.dll',recursive=True)
|
files = glob.glob('**\*libcodec2*.dll',recursive=True)
|
||||||
else:
|
else:
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
try:
|
try:
|
||||||
|
@ -79,15 +79,15 @@ for file in files:
|
||||||
structlog.get_logger("structlog").warning("[C2 ] Libcodec2 found but not loaded", path=file, e=e)
|
structlog.get_logger("structlog").warning("[C2 ] Libcodec2 found but not loaded", path=file, e=e)
|
||||||
|
|
||||||
|
|
||||||
# quit module if codec2 cant be loaded
|
# quit module if codec2 cant be loaded
|
||||||
if not 'api' in locals():
|
if not 'api' in locals():
|
||||||
structlog.get_logger("structlog").critical("[C2 ] Libcodec2 not loaded", path=file)
|
structlog.get_logger("structlog").critical("[C2 ] Libcodec2 not loaded", path=file)
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ctypes function init
|
# ctypes function init
|
||||||
|
|
||||||
#api.freedv_set_tuning_range.restype = c_int
|
#api.freedv_set_tuning_range.restype = c_int
|
||||||
#api.freedv_set_tuning_range.argype = [c_void_p, c_float, c_float]
|
#api.freedv_set_tuning_range.argype = [c_void_p, c_float, c_float]
|
||||||
|
@ -121,24 +121,24 @@ api.freedv_get_n_max_modem_samples.restype = c_int
|
||||||
|
|
||||||
api.freedv_set_frames_per_burst.argtype = [c_void_p, c_int]
|
api.freedv_set_frames_per_burst.argtype = [c_void_p, c_int]
|
||||||
api.freedv_set_frames_per_burst.restype = c_void_p
|
api.freedv_set_frames_per_burst.restype = c_void_p
|
||||||
|
|
||||||
api.freedv_get_rx_status.argtype = [c_void_p]
|
api.freedv_get_rx_status.argtype = [c_void_p]
|
||||||
api.freedv_get_rx_status.restype = c_int
|
api.freedv_get_rx_status.restype = c_int
|
||||||
|
|
||||||
api.freedv_get_modem_stats.argtype = [c_void_p, c_void_p, c_void_p]
|
api.freedv_get_modem_stats.argtype = [c_void_p, c_void_p, c_void_p]
|
||||||
api.freedv_get_modem_stats.restype = c_int
|
api.freedv_get_modem_stats.restype = c_int
|
||||||
|
|
||||||
api.freedv_get_n_tx_postamble_modem_samples.argtype = [c_void_p]
|
api.freedv_get_n_tx_postamble_modem_samples.argtype = [c_void_p]
|
||||||
api.freedv_get_n_tx_postamble_modem_samples.restype = c_int
|
api.freedv_get_n_tx_postamble_modem_samples.restype = c_int
|
||||||
|
|
||||||
api.freedv_get_n_tx_preamble_modem_samples.argtype = [c_void_p]
|
api.freedv_get_n_tx_preamble_modem_samples.argtype = [c_void_p]
|
||||||
api.freedv_get_n_tx_preamble_modem_samples.restype = c_int
|
api.freedv_get_n_tx_preamble_modem_samples.restype = c_int
|
||||||
|
|
||||||
api.freedv_get_n_tx_modem_samples.argtype = [c_void_p]
|
api.freedv_get_n_tx_modem_samples.argtype = [c_void_p]
|
||||||
api.freedv_get_n_tx_modem_samples.restype = c_int
|
api.freedv_get_n_tx_modem_samples.restype = c_int
|
||||||
|
|
||||||
api.freedv_get_n_max_modem_samples.argtype = [c_void_p]
|
api.freedv_get_n_max_modem_samples.argtype = [c_void_p]
|
||||||
api.freedv_get_n_max_modem_samples.restype = c_int
|
api.freedv_get_n_max_modem_samples.restype = c_int
|
||||||
|
|
||||||
api.FREEDV_FS_8000 = 8000
|
api.FREEDV_FS_8000 = 8000
|
||||||
api.FREEDV_MODE_DATAC1 = 10
|
api.FREEDV_MODE_DATAC1 = 10
|
||||||
|
@ -152,13 +152,13 @@ api.FREEDV_MODE_FSK_LDPC = 9
|
||||||
class ADVANCED(ctypes.Structure):
|
class ADVANCED(ctypes.Structure):
|
||||||
""" """
|
""" """
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
("interleave_frames", ctypes.c_int),
|
("interleave_frames", ctypes.c_int),
|
||||||
("M", ctypes.c_int),
|
("M", ctypes.c_int),
|
||||||
("Rs", ctypes.c_int),
|
("Rs", ctypes.c_int),
|
||||||
("Fs", ctypes.c_int),
|
("Fs", ctypes.c_int),
|
||||||
("first_tone", ctypes.c_int),
|
("first_tone", ctypes.c_int),
|
||||||
("tone_spacing", ctypes.c_int),
|
("tone_spacing", ctypes.c_int),
|
||||||
("codename", ctypes.c_char_p),
|
("codename", ctypes.c_char_p),
|
||||||
]
|
]
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -232,9 +232,9 @@ class MODEMSTATS(ctypes.Structure):
|
||||||
("f_est", (ctypes.c_float * MODEM_STATS_MAX_F_EST)), # How many samples in the eye diagram
|
("f_est", (ctypes.c_float * MODEM_STATS_MAX_F_EST)), # How many samples in the eye diagram
|
||||||
("fft_buf", (ctypes.c_float * MODEM_STATS_NSPEC * 2)),
|
("fft_buf", (ctypes.c_float * MODEM_STATS_NSPEC * 2)),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Return code flags for freedv_get_rx_status() function
|
# Return code flags for freedv_get_rx_status() function
|
||||||
api.FREEDV_RX_TRIAL_SYNC = 0x1 # demodulator has trial sync
|
api.FREEDV_RX_TRIAL_SYNC = 0x1 # demodulator has trial sync
|
||||||
api.FREEDV_RX_SYNC = 0x2 # demodulator has sync
|
api.FREEDV_RX_SYNC = 0x2 # demodulator has sync
|
||||||
|
@ -264,7 +264,7 @@ api.rx_sync_flags_to_text = [
|
||||||
class audio_buffer:
|
class audio_buffer:
|
||||||
"""
|
"""
|
||||||
thread safe audio buffer, which fits to needs of codec2
|
thread safe audio buffer, which fits to needs of codec2
|
||||||
|
|
||||||
made by David Rowe, VK5DGR
|
made by David Rowe, VK5DGR
|
||||||
"""
|
"""
|
||||||
# a buffer of int16 samples, using a fixed length numpy array self.buffer for storage
|
# a buffer of int16 samples, using a fixed length numpy array self.buffer for storage
|
||||||
|
@ -280,7 +280,7 @@ class audio_buffer:
|
||||||
Push new data to buffer
|
Push new data to buffer
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
samples:
|
samples:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ class audio_buffer:
|
||||||
"""
|
"""
|
||||||
get data from buffer in size of NIN
|
get data from buffer in size of NIN
|
||||||
Args:
|
Args:
|
||||||
size:
|
size:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ class audio_buffer:
|
||||||
self.buffer[:self.nbuffer] = self.buffer[size:size+self.nbuffer]
|
self.buffer[:self.nbuffer] = self.buffer[size:size+self.nbuffer]
|
||||||
assert self.nbuffer >= 0
|
assert self.nbuffer >= 0
|
||||||
self.mutex.release()
|
self.mutex.release()
|
||||||
|
|
||||||
# resampler ---------------------------------------------------------
|
# resampler ---------------------------------------------------------
|
||||||
|
|
||||||
api.FDMDV_OS_48 = int(6) # oversampling rate
|
api.FDMDV_OS_48 = int(6) # oversampling rate
|
||||||
|
@ -327,8 +327,8 @@ class resampler:
|
||||||
structlog.get_logger("structlog").debug("[C2 ] create 48<->8 kHz resampler")
|
structlog.get_logger("structlog").debug("[C2 ] create 48<->8 kHz resampler")
|
||||||
self.filter_mem8 = np.zeros(self.MEM8, dtype=np.int16)
|
self.filter_mem8 = np.zeros(self.MEM8, dtype=np.int16)
|
||||||
self.filter_mem48 = np.zeros(self.MEM48)
|
self.filter_mem48 = np.zeros(self.MEM48)
|
||||||
|
|
||||||
|
|
||||||
def resample48_to_8(self,in48):
|
def resample48_to_8(self,in48):
|
||||||
"""
|
"""
|
||||||
audio resampler integration from codec2
|
audio resampler integration from codec2
|
||||||
|
|
134
tnc/daemon.py
134
tnc/daemon.py
|
@ -37,8 +37,8 @@ def signal_handler(sig, frame):
|
||||||
"""
|
"""
|
||||||
signal handler for closing the network socket on app exit
|
signal handler for closing the network socket on app exit
|
||||||
Args:
|
Args:
|
||||||
sig:
|
sig:
|
||||||
frame:
|
frame:
|
||||||
|
|
||||||
Returns: system exit
|
Returns: system exit
|
||||||
|
|
||||||
|
@ -51,15 +51,15 @@ signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
|
|
||||||
class DAEMON():
|
class DAEMON():
|
||||||
"""
|
"""
|
||||||
daemon class
|
daemon class
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# load crc engine
|
# load crc engine
|
||||||
self.crc_algorithm = crcengine.new('crc16-ccitt-false') # load crc8 library
|
self.crc_algorithm = crcengine.new('crc16-ccitt-false') # load crc8 library
|
||||||
|
|
||||||
self.daemon_queue = sock.DAEMON_QUEUE
|
self.daemon_queue = sock.DAEMON_QUEUE
|
||||||
update_audio_devices = threading.Thread(target=self.update_audio_devices, name="UPDATE_AUDIO_DEVICES", daemon=True)
|
update_audio_devices = threading.Thread(target=self.update_audio_devices, name="UPDATE_AUDIO_DEVICES", daemon=True)
|
||||||
update_audio_devices.start()
|
update_audio_devices.start()
|
||||||
|
@ -69,23 +69,23 @@ class DAEMON():
|
||||||
|
|
||||||
worker = threading.Thread(target=self.worker, name="WORKER", daemon=True)
|
worker = threading.Thread(target=self.worker, name="WORKER", daemon=True)
|
||||||
worker.start()
|
worker.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def update_audio_devices(self):
|
def update_audio_devices(self):
|
||||||
"""
|
"""
|
||||||
update audio devices and set to static
|
update audio devices and set to static
|
||||||
"""
|
"""
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
if not static.TNCSTARTED:
|
if not static.TNCSTARTED:
|
||||||
|
|
||||||
static.AUDIO_INPUT_DEVICES, static.AUDIO_OUTPUT_DEVICES = audio.get_audio_devices()
|
static.AUDIO_INPUT_DEVICES, static.AUDIO_OUTPUT_DEVICES = audio.get_audio_devices()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
def update_serial_devices(self):
|
def update_serial_devices(self):
|
||||||
"""
|
"""
|
||||||
update serial devices and set to static
|
update serial devices and set to static
|
||||||
|
@ -96,26 +96,26 @@ class DAEMON():
|
||||||
serial_devices = []
|
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:
|
||||||
|
|
||||||
# calculate hex of hwid if we have unique names
|
# calculate hex of hwid if we have unique names
|
||||||
crc_hwid = self.crc_algorithm(bytes(hwid, encoding='utf-8'))
|
crc_hwid = self.crc_algorithm(bytes(hwid, encoding='utf-8'))
|
||||||
crc_hwid = crc_hwid.to_bytes(2, byteorder='big')
|
crc_hwid = crc_hwid.to_bytes(2, byteorder='big')
|
||||||
crc_hwid = crc_hwid.hex()
|
crc_hwid = crc_hwid.hex()
|
||||||
description = desc + ' [' + crc_hwid + ']'
|
description = desc + ' [' + crc_hwid + ']'
|
||||||
serial_devices.append({"port": str(port), "description": str(description) })
|
serial_devices.append({"port": str(port), "description": str(description) })
|
||||||
|
|
||||||
static.SERIAL_DEVICES = serial_devices
|
static.SERIAL_DEVICES = serial_devices
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def worker(self):
|
def worker(self):
|
||||||
"""
|
"""
|
||||||
a worker for the received commands
|
a worker for the received commands
|
||||||
"""
|
"""
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
|
|
||||||
data = self.daemon_queue.get()
|
data = self.daemon_queue.get()
|
||||||
|
|
||||||
# data[1] mycall
|
# data[1] mycall
|
||||||
|
@ -141,81 +141,81 @@ class DAEMON():
|
||||||
# data[21] enable FSK
|
# data[21] enable FSK
|
||||||
# data[22] tx-audio-level
|
# data[22] tx-audio-level
|
||||||
# data[23] respond_to_cq
|
# data[23] respond_to_cq
|
||||||
|
|
||||||
if data[0] == 'STARTTNC':
|
if data[0] == 'STARTTNC':
|
||||||
structlog.get_logger("structlog").warning("[DMN] Starting TNC", rig=data[5], port=data[6])
|
structlog.get_logger("structlog").warning("[DMN] Starting TNC", rig=data[5], port=data[6])
|
||||||
|
|
||||||
# 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('--port')
|
options.append('--port')
|
||||||
options.append(str(static.DAEMONPORT - 1))
|
options.append(str(static.DAEMONPORT - 1))
|
||||||
|
|
||||||
options.append('--mycall')
|
options.append('--mycall')
|
||||||
options.append(data[1])
|
options.append(data[1])
|
||||||
|
|
||||||
options.append('--mygrid')
|
options.append('--mygrid')
|
||||||
options.append(data[2])
|
options.append(data[2])
|
||||||
|
|
||||||
options.append('--rx')
|
options.append('--rx')
|
||||||
options.append(data[3])
|
options.append(data[3])
|
||||||
|
|
||||||
options.append('--tx')
|
options.append('--tx')
|
||||||
options.append(data[4])
|
options.append(data[4])
|
||||||
|
|
||||||
# if radiocontrol != disabled
|
# if radiocontrol != disabled
|
||||||
# this should hopefully avoid a ton of problems if we are just running in
|
# this should hopefully avoid a ton of problems if we are just running in
|
||||||
# disabled mode
|
# disabled mode
|
||||||
|
|
||||||
if data[13] != 'disabled':
|
if data[13] != 'disabled':
|
||||||
|
|
||||||
options.append('--devicename')
|
options.append('--devicename')
|
||||||
options.append(data[5])
|
options.append(data[5])
|
||||||
|
|
||||||
options.append('--deviceport')
|
options.append('--deviceport')
|
||||||
options.append(data[6])
|
options.append(data[6])
|
||||||
|
|
||||||
options.append('--serialspeed')
|
options.append('--serialspeed')
|
||||||
options.append(data[7])
|
options.append(data[7])
|
||||||
|
|
||||||
options.append('--pttprotocol')
|
options.append('--pttprotocol')
|
||||||
options.append(data[8])
|
options.append(data[8])
|
||||||
|
|
||||||
options.append('--pttport')
|
options.append('--pttport')
|
||||||
options.append(data[9])
|
options.append(data[9])
|
||||||
|
|
||||||
options.append('--data_bits')
|
options.append('--data_bits')
|
||||||
options.append(data[10])
|
options.append(data[10])
|
||||||
|
|
||||||
options.append('--stop_bits')
|
options.append('--stop_bits')
|
||||||
options.append(data[11])
|
options.append(data[11])
|
||||||
|
|
||||||
options.append('--handshake')
|
options.append('--handshake')
|
||||||
options.append(data[12])
|
options.append(data[12])
|
||||||
|
|
||||||
options.append('--radiocontrol')
|
options.append('--radiocontrol')
|
||||||
options.append(data[13])
|
options.append(data[13])
|
||||||
|
|
||||||
if data[13] != 'rigctld':
|
if data[13] != 'rigctld':
|
||||||
options.append('--rigctld_ip')
|
options.append('--rigctld_ip')
|
||||||
options.append(data[14])
|
options.append(data[14])
|
||||||
|
|
||||||
options.append('--rigctld_port')
|
options.append('--rigctld_port')
|
||||||
options.append(data[15])
|
options.append(data[15])
|
||||||
|
|
||||||
if data[16] == 'True':
|
if data[16] == 'True':
|
||||||
options.append('--scatter')
|
options.append('--scatter')
|
||||||
|
|
||||||
if data[17] == 'True':
|
if data[17] == 'True':
|
||||||
options.append('--fft')
|
options.append('--fft')
|
||||||
|
|
||||||
if data[18] == 'True':
|
if data[18] == 'True':
|
||||||
options.append('--500hz')
|
options.append('--500hz')
|
||||||
|
|
||||||
|
|
||||||
options.append('--tuning_range_fmin')
|
options.append('--tuning_range_fmin')
|
||||||
options.append(data[19])
|
options.append(data[19])
|
||||||
|
|
||||||
options.append('--tuning_range_fmax')
|
options.append('--tuning_range_fmax')
|
||||||
options.append(data[20])
|
options.append(data[20])
|
||||||
|
|
||||||
|
@ -224,13 +224,13 @@ class DAEMON():
|
||||||
# options.append('--fsk')
|
# options.append('--fsk')
|
||||||
|
|
||||||
options.append('--tx-audio-level')
|
options.append('--tx-audio-level')
|
||||||
options.append(data[22])
|
options.append(data[22])
|
||||||
|
|
||||||
if data[23] == 'True':
|
if data[23] == 'True':
|
||||||
options.append('--qrv')
|
options.append('--qrv')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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:
|
||||||
|
@ -239,10 +239,10 @@ class DAEMON():
|
||||||
command.append('./freedata-tnc')
|
command.append('./freedata-tnc')
|
||||||
elif sys.platform == 'win32' or sys.platform == 'win64':
|
elif sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
command.append('freedata-tnc.exe')
|
command.append('freedata-tnc.exe')
|
||||||
|
|
||||||
command += options
|
command += options
|
||||||
p = subprocess.Popen(command)
|
p = subprocess.Popen(command)
|
||||||
|
|
||||||
atexit.register(p.kill)
|
atexit.register(p.kill)
|
||||||
|
|
||||||
structlog.get_logger("structlog").info("[DMN] TNC started", path="binary")
|
structlog.get_logger("structlog").info("[DMN] TNC started", path="binary")
|
||||||
|
@ -252,7 +252,7 @@ class DAEMON():
|
||||||
command.append('python3')
|
command.append('python3')
|
||||||
elif sys.platform == 'win32' or sys.platform == 'win64':
|
elif sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
command.append('python')
|
command.append('python')
|
||||||
|
|
||||||
command.append('main.py')
|
command.append('main.py')
|
||||||
command += options
|
command += options
|
||||||
p = subprocess.Popen(command)
|
p = subprocess.Popen(command)
|
||||||
|
@ -269,7 +269,7 @@ class DAEMON():
|
||||||
structlog.get_logger("structlog").warning("[DMN] Stopping TNC")
|
structlog.get_logger("structlog").warning("[DMN] Stopping TNC")
|
||||||
#os.kill(static.TNCPROCESS, signal.SIGKILL)
|
#os.kill(static.TNCPROCESS, signal.SIGKILL)
|
||||||
static.TNCSTARTED = False
|
static.TNCSTARTED = False
|
||||||
'''
|
'''
|
||||||
# data[1] devicename
|
# data[1] devicename
|
||||||
# data[2] deviceport
|
# data[2] deviceport
|
||||||
# data[3] serialspeed
|
# data[3] serialspeed
|
||||||
|
@ -306,15 +306,15 @@ class DAEMON():
|
||||||
import rigctld as rig
|
import rigctld as rig
|
||||||
else:
|
else:
|
||||||
import rigdummy as rig
|
import rigdummy as rig
|
||||||
|
|
||||||
hamlib = rig.radio()
|
hamlib = rig.radio()
|
||||||
hamlib.open_rig(devicename=devicename, deviceport=deviceport, hamlib_ptt_type=pttprotocol, serialspeed=serialspeed, pttport=pttport, data_bits=data_bits, stop_bits=stop_bits, handshake=handshake, rigctld_ip=rigctld_ip, rigctld_port = rigctld_port)
|
hamlib.open_rig(devicename=devicename, deviceport=deviceport, hamlib_ptt_type=pttprotocol, serialspeed=serialspeed, pttport=pttport, data_bits=data_bits, stop_bits=stop_bits, handshake=handshake, rigctld_ip=rigctld_ip, rigctld_port = rigctld_port)
|
||||||
|
|
||||||
hamlib_version = rig.hamlib_version
|
hamlib_version = rig.hamlib_version
|
||||||
|
|
||||||
hamlib.set_ptt(True)
|
hamlib.set_ptt(True)
|
||||||
pttstate = hamlib.get_ptt()
|
pttstate = hamlib.get_ptt()
|
||||||
|
|
||||||
if pttstate:
|
if pttstate:
|
||||||
structlog.get_logger("structlog").info("[DMN] Hamlib PTT", status = 'SUCCESS')
|
structlog.get_logger("structlog").info("[DMN] Hamlib PTT", status = 'SUCCESS')
|
||||||
response = {'command': 'test_hamlib', 'result': 'SUCCESS'}
|
response = {'command': 'test_hamlib', 'result': 'SUCCESS'}
|
||||||
|
@ -324,13 +324,13 @@ class DAEMON():
|
||||||
else:
|
else:
|
||||||
structlog.get_logger("structlog").error("[DMN] Hamlib PTT", status = 'FAILED')
|
structlog.get_logger("structlog").error("[DMN] Hamlib PTT", status = 'FAILED')
|
||||||
response = {'command': 'test_hamlib', 'result': 'FAILED'}
|
response = {'command': 'test_hamlib', 'result': 'FAILED'}
|
||||||
|
|
||||||
hamlib.set_ptt(False)
|
hamlib.set_ptt(False)
|
||||||
hamlib.close_rig()
|
hamlib.close_rig()
|
||||||
|
|
||||||
jsondata = json.dumps(response)
|
jsondata = json.dumps(response)
|
||||||
sock.SOCKET_QUEUE.put(jsondata)
|
sock.SOCKET_QUEUE.put(jsondata)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
@ -343,27 +343,27 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# --------------------------------------------GET PARAMETER INPUTS
|
# --------------------------------------------GET PARAMETER INPUTS
|
||||||
PARSER = argparse.ArgumentParser(description='FreeDATA Daemon')
|
PARSER = argparse.ArgumentParser(description='FreeDATA Daemon')
|
||||||
PARSER.add_argument('--port', dest="socket_port",default=3001, help="Socket port in the range of 1024-65536", type=int)
|
PARSER.add_argument('--port', dest="socket_port",default=3001, help="Socket port in the range of 1024-65536", type=int)
|
||||||
ARGS = PARSER.parse_args()
|
ARGS = PARSER.parse_args()
|
||||||
|
|
||||||
static.DAEMONPORT = ARGS.socket_port
|
static.DAEMONPORT = ARGS.socket_port
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if sys.platform == 'linux':
|
if sys.platform == 'linux':
|
||||||
logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'daemon'
|
logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'daemon'
|
||||||
|
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'daemon'
|
logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'daemon'
|
||||||
|
|
||||||
if sys.platform == 'win32' or sys.platform == 'win64':
|
if sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'daemon'
|
logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'daemon'
|
||||||
|
|
||||||
if not os.path.exists(logging_path):
|
if not os.path.exists(logging_path):
|
||||||
os.makedirs(logging_path)
|
os.makedirs(logging_path)
|
||||||
log_handler.setup_logging(logging_path)
|
log_handler.setup_logging(logging_path)
|
||||||
except:
|
except:
|
||||||
structlog.get_logger("structlog").error("[DMN] logger init error")
|
structlog.get_logger("structlog").error("[DMN] logger init error")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
structlog.get_logger("structlog").info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT)
|
structlog.get_logger("structlog").info("[DMN] Starting TCP/IP socket", port=static.DAEMONPORT)
|
||||||
|
@ -379,7 +379,7 @@ if __name__ == '__main__':
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
daemon = DAEMON()
|
daemon = DAEMON()
|
||||||
|
|
||||||
|
|
||||||
structlog.get_logger("structlog").info("[DMN] Starting FreeDATA Daemon", author="DJ2LS", year="2022", version=static.VERSION)
|
structlog.get_logger("structlog").info("[DMN] Starting FreeDATA Daemon", author="DJ2LS", year="2022", version=static.VERSION)
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@ def wait(seconds):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
seconds:
|
seconds:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -26,18 +26,18 @@ def wait(seconds):
|
||||||
while time.time() < timeout:
|
while time.time() < timeout:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_crc_8(data):
|
def get_crc_8(data):
|
||||||
"""Author: DJ2LS
|
"""Author: DJ2LS
|
||||||
|
|
||||||
Get the CRC8 of a byte string
|
Get the CRC8 of a byte string
|
||||||
|
|
||||||
param: data = bytes()
|
param: data = bytes()
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ def get_crc_8(data):
|
||||||
|
|
||||||
def get_crc_16(data):
|
def get_crc_16(data):
|
||||||
"""Author: DJ2LS
|
"""Author: DJ2LS
|
||||||
|
|
||||||
Get the CRC16 of a byte string
|
Get the CRC16 of a byte string
|
||||||
|
|
||||||
param: data = bytes()
|
param: data = bytes()
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -68,35 +68,35 @@ def get_crc_16(data):
|
||||||
|
|
||||||
def get_crc_24(data):
|
def get_crc_24(data):
|
||||||
"""Author: DJ2LS
|
"""Author: DJ2LS
|
||||||
|
|
||||||
Get the CRC24-OPENPGP of a byte string
|
Get the CRC24-OPENPGP of a byte string
|
||||||
https://github.com/GardenTools/CrcEngine#examples
|
https://github.com/GardenTools/CrcEngine#examples
|
||||||
|
|
||||||
param: data = bytes()
|
param: data = bytes()
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
crc_algorithm = crcengine.create(0x864cfb, 24, 0xb704ce, ref_in=False,
|
crc_algorithm = crcengine.create(0x864cfb, 24, 0xb704ce, ref_in=False,
|
||||||
ref_out=False, xor_out=0,
|
ref_out=False, xor_out=0,
|
||||||
name='crc-24-openpgp')
|
name='crc-24-openpgp')
|
||||||
crc_data = crc_algorithm(data)
|
crc_data = crc_algorithm(data)
|
||||||
crc_data = crc_data.to_bytes(3, byteorder='big')
|
crc_data = crc_data.to_bytes(3, byteorder='big')
|
||||||
return crc_data
|
return crc_data
|
||||||
|
|
||||||
|
|
||||||
def get_crc_32(data):
|
def get_crc_32(data):
|
||||||
"""Author: DJ2LS
|
"""Author: DJ2LS
|
||||||
|
|
||||||
Get the CRC32 of a byte string
|
Get the CRC32 of a byte string
|
||||||
|
|
||||||
param: data = bytes()
|
param: data = bytes()
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -111,12 +111,12 @@ def add_to_heard_stations(dxcallsign, dxgrid, datatype, snr, offset, frequency):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dxcallsign:
|
dxcallsign:
|
||||||
dxgrid:
|
dxgrid:
|
||||||
datatype:
|
datatype:
|
||||||
snr:
|
snr:
|
||||||
offset:
|
offset:
|
||||||
frequency:
|
frequency:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ def callsign_to_bytes(callsign):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
callsign:
|
callsign:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -171,21 +171,21 @@ def callsign_to_bytes(callsign):
|
||||||
#-13 Weather stations
|
#-13 Weather stations
|
||||||
#-14 Truckers or generally full time drivers
|
#-14 Truckers or generally full time drivers
|
||||||
#-15 generic additional station, digi, mobile, wx, etc
|
#-15 generic additional station, digi, mobile, wx, etc
|
||||||
|
|
||||||
# try converting to bytestring if possible type string
|
# try converting to bytestring if possible type string
|
||||||
try:
|
try:
|
||||||
callsign = bytes(callsign, 'utf-8')
|
callsign = bytes(callsign, 'utf-8')
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign )
|
# we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign )
|
||||||
callsign = callsign.split(b'-')
|
callsign = callsign.split(b'-')
|
||||||
try:
|
try:
|
||||||
ssid = int(callsign[1])
|
ssid = int(callsign[1])
|
||||||
except:
|
except:
|
||||||
ssid = 0
|
ssid = 0
|
||||||
|
|
||||||
#callsign = callsign[0]
|
#callsign = callsign[0]
|
||||||
#bytestring = bytearray(8)
|
#bytestring = bytearray(8)
|
||||||
#bytestring[:len(callsign)] = callsign
|
#bytestring[:len(callsign)] = callsign
|
||||||
#bytestring[7:8] = bytes([ssid])
|
#bytestring[7:8] = bytes([ssid])
|
||||||
|
@ -196,14 +196,14 @@ def callsign_to_bytes(callsign):
|
||||||
return encode_call(callsign + ssid)
|
return encode_call(callsign + ssid)
|
||||||
|
|
||||||
|
|
||||||
#return bytes(bytestring)
|
#return bytes(bytestring)
|
||||||
|
|
||||||
def bytes_to_callsign(bytestring):
|
def bytes_to_callsign(bytestring):
|
||||||
"""
|
"""
|
||||||
Convert our callsign, received by a frame to a callsign in a human readable format
|
Convert our callsign, received by a frame to a callsign in a human readable format
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
bytestring:
|
bytestring:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bytes
|
bytes
|
||||||
|
@ -227,8 +227,8 @@ def bytes_to_callsign(bytestring):
|
||||||
#-13 Weather stations
|
#-13 Weather stations
|
||||||
#-14 Truckers or generally full time drivers
|
#-14 Truckers or generally full time drivers
|
||||||
#-15 generic additional station, digi, mobile, wx, etc
|
#-15 generic additional station, digi, mobile, wx, etc
|
||||||
|
|
||||||
# we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign )
|
# we need to do this step to reduce the needed paypload by the callsign ( stripping "-" out of the callsign )
|
||||||
'''
|
'''
|
||||||
callsign = bytes(bytestring[:7])
|
callsign = bytes(bytestring[:7])
|
||||||
callsign = callsign.rstrip(b'\x00')
|
callsign = callsign.rstrip(b'\x00')
|
||||||
|
@ -238,8 +238,8 @@ def bytes_to_callsign(bytestring):
|
||||||
callsign = callsign.decode('utf-8')
|
callsign = callsign.decode('utf-8')
|
||||||
callsign = callsign + str(ssid)
|
callsign = callsign + str(ssid)
|
||||||
callsign = callsign.encode('utf-8')
|
callsign = callsign.encode('utf-8')
|
||||||
|
|
||||||
return bytes(callsign)
|
return bytes(callsign)
|
||||||
'''
|
'''
|
||||||
decoded = decode_call(bytestring)
|
decoded = decode_call(bytestring)
|
||||||
callsign = decoded[:-1]
|
callsign = decoded[:-1]
|
||||||
|
@ -254,23 +254,23 @@ def check_callsign(callsign:bytes, crc_to_check:bytes):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
callsign: Callsign which we want to check
|
callsign: Callsign which we want to check
|
||||||
crc_to_check: The CRC which we want the callsign to check against
|
crc_to_check: The CRC which we want the callsign to check against
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
[True, Callsign + SSID]
|
[True, Callsign + SSID]
|
||||||
False
|
False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
print(callsign)
|
print(callsign)
|
||||||
try:
|
try:
|
||||||
callsign = callsign.split(b'-')
|
callsign = callsign.split(b'-')
|
||||||
callsign = callsign[0] # we want the callsign without SSID
|
callsign = callsign[0] # we want the callsign without SSID
|
||||||
|
|
||||||
except:
|
except:
|
||||||
callsign = callsign
|
callsign = callsign
|
||||||
|
|
||||||
for ssid in static.SSID_LIST:
|
for ssid in static.SSID_LIST:
|
||||||
call_with_ssid = bytearray(callsign)
|
call_with_ssid = bytearray(callsign)
|
||||||
call_with_ssid.extend('-'.encode('utf-8'))
|
call_with_ssid.extend('-'.encode('utf-8'))
|
||||||
call_with_ssid.extend(str(ssid).encode('utf-8'))
|
call_with_ssid.extend(str(ssid).encode('utf-8'))
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ def check_callsign(callsign:bytes, crc_to_check:bytes):
|
||||||
if callsign_crc == crc_to_check:
|
if callsign_crc == crc_to_check:
|
||||||
print(call_with_ssid)
|
print(call_with_ssid)
|
||||||
return [True, bytes(call_with_ssid)]
|
return [True, bytes(call_with_ssid)]
|
||||||
|
|
||||||
return [False, ""]
|
return [False, ""]
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ def decode_grid(b_code_word:bytes):
|
||||||
"""
|
"""
|
||||||
code_word = int.from_bytes(b_code_word, byteorder='big', signed=False)
|
code_word = int.from_bytes(b_code_word, byteorder='big', signed=False)
|
||||||
|
|
||||||
grid = chr((code_word & 0b11111) + 65)
|
grid = chr((code_word & 0b11111) + 65)
|
||||||
code_word = code_word >> 5
|
code_word = code_word >> 5
|
||||||
|
|
||||||
grid = chr((code_word & 0b11111) + 65) + grid
|
grid = chr((code_word & 0b11111) + 65) + grid
|
||||||
|
@ -359,7 +359,7 @@ def encode_call(call):
|
||||||
out_code_word = int(0)
|
out_code_word = int(0)
|
||||||
|
|
||||||
call = call.upper() # upper case to be save
|
call = call.upper() # upper case to be save
|
||||||
|
|
||||||
for x in call:
|
for x in call:
|
||||||
int_val = ord(x)-48 # -48 reduce bits, begin with first number utf8 table
|
int_val = ord(x)-48 # -48 reduce bits, begin with first number utf8 table
|
||||||
out_code_word = out_code_word << 6 # shift left 6 bit, making space for a new char
|
out_code_word = out_code_word << 6 # shift left 6 bit, making space for a new char
|
||||||
|
|
|
@ -3,7 +3,7 @@ def setup_logging(filename):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filename:
|
filename:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
|
92
tnc/main.py
92
tnc/main.py
|
@ -33,7 +33,7 @@ def signal_handler(sig, frame):
|
||||||
a signal handler, which closes the network/socket when closing the application
|
a signal handler, which closes the network/socket when closing the application
|
||||||
Args:
|
Args:
|
||||||
sig: signal
|
sig: signal
|
||||||
frame:
|
frame:
|
||||||
|
|
||||||
Returns: system exit
|
Returns: system exit
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ def signal_handler(sig, frame):
|
||||||
print('Closing TNC...')
|
print('Closing TNC...')
|
||||||
sock.CLOSE_SIGNAL = True
|
sock.CLOSE_SIGNAL = True
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -51,31 +51,31 @@ if __name__ == '__main__':
|
||||||
PARSER = argparse.ArgumentParser(description='FreeDATA TNC')
|
PARSER = argparse.ArgumentParser(description='FreeDATA TNC')
|
||||||
PARSER.add_argument('--mycall', dest="mycall", default="AA0AA", help="My callsign", type=str)
|
PARSER.add_argument('--mycall', dest="mycall", default="AA0AA", help="My callsign", type=str)
|
||||||
PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], help="SSID list we are responding to", type=str)
|
PARSER.add_argument('--ssid', dest="ssid_list", nargs='*', default=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], help="SSID list we are responding to", type=str)
|
||||||
PARSER.add_argument('--mygrid', dest="mygrid", default="JN12AA", help="My gridsquare", type=str)
|
PARSER.add_argument('--mygrid', dest="mygrid", default="JN12AA", help="My gridsquare", type=str)
|
||||||
PARSER.add_argument('--rx', dest="audio_input_device", default=0, help="listening sound card", type=int)
|
PARSER.add_argument('--rx', dest="audio_input_device", default=0, help="listening sound card", type=int)
|
||||||
PARSER.add_argument('--tx', dest="audio_output_device", default=0, help="transmitting sound card", type=int)
|
PARSER.add_argument('--tx', dest="audio_output_device", default=0, help="transmitting sound card", type=int)
|
||||||
PARSER.add_argument('--port', dest="socket_port", default=3000, help="Socket port in the range of 1024-65536", type=int)
|
PARSER.add_argument('--port', dest="socket_port", default=3000, help="Socket port in the range of 1024-65536", type=int)
|
||||||
PARSER.add_argument('--deviceport', dest="hamlib_device_port", default="/dev/ttyUSB0", help="Hamlib device port", type=str)
|
PARSER.add_argument('--deviceport', dest="hamlib_device_port", default="/dev/ttyUSB0", help="Hamlib device port", type=str)
|
||||||
PARSER.add_argument('--devicename', dest="hamlib_device_name", default="2028", help="Hamlib device name", type=str)
|
PARSER.add_argument('--devicename', dest="hamlib_device_name", default="2028", help="Hamlib device name", type=str)
|
||||||
PARSER.add_argument('--serialspeed', dest="hamlib_serialspeed", choices=[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200], default=9600, help="Serialspeed", type=int)
|
PARSER.add_argument('--serialspeed', dest="hamlib_serialspeed", choices=[1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200], default=9600, help="Serialspeed", type=int)
|
||||||
PARSER.add_argument('--pttprotocol', dest="hamlib_ptt_type", choices=['USB', 'RIG', 'RTS', 'DTR', 'CM108', 'MICDATA', 'PARALLEL', 'DTR-H', 'DTR-L', 'NONE'], default='USB', help="PTT Type", type=str)
|
PARSER.add_argument('--pttprotocol', dest="hamlib_ptt_type", choices=['USB', 'RIG', 'RTS', 'DTR', 'CM108', 'MICDATA', 'PARALLEL', 'DTR-H', 'DTR-L', 'NONE'], default='USB', help="PTT Type", type=str)
|
||||||
PARSER.add_argument('--pttport', dest="hamlib_ptt_port", default="/dev/ttyUSB0", help="PTT Port", type=str)
|
PARSER.add_argument('--pttport', dest="hamlib_ptt_port", default="/dev/ttyUSB0", help="PTT Port", type=str)
|
||||||
PARSER.add_argument('--data_bits', dest="hamlib_data_bits", choices=[7, 8], default=8, help="Hamlib data bits", type=int)
|
PARSER.add_argument('--data_bits', dest="hamlib_data_bits", choices=[7, 8], default=8, help="Hamlib data bits", type=int)
|
||||||
PARSER.add_argument('--stop_bits', dest="hamlib_stop_bits", choices=[1, 2], default=1, help="Hamlib stop bits", type=int)
|
PARSER.add_argument('--stop_bits', dest="hamlib_stop_bits", choices=[1, 2], default=1, help="Hamlib stop bits", type=int)
|
||||||
PARSER.add_argument('--handshake', dest="hamlib_handshake", default="None", help="Hamlib handshake", type=str)
|
PARSER.add_argument('--handshake', dest="hamlib_handshake", default="None", help="Hamlib handshake", type=str)
|
||||||
PARSER.add_argument('--radiocontrol', dest="hamlib_radiocontrol", choices=['disabled', 'direct', 'rigctl', 'rigctld'], default="disabled", help="Set how you want to control your radio")
|
PARSER.add_argument('--radiocontrol', dest="hamlib_radiocontrol", choices=['disabled', 'direct', 'rigctl', 'rigctld'], default="disabled", help="Set how you want to control your radio")
|
||||||
PARSER.add_argument('--rigctld_port', dest="rigctld_port", default=4532, type=int, help="Set rigctld port")
|
PARSER.add_argument('--rigctld_port', dest="rigctld_port", default=4532, type=int, help="Set rigctld port")
|
||||||
PARSER.add_argument('--rigctld_ip', dest="rigctld_ip", default="localhost", help="Set rigctld ip")
|
PARSER.add_argument('--rigctld_ip', dest="rigctld_ip", default="localhost", help="Set rigctld ip")
|
||||||
PARSER.add_argument('--scatter', dest="send_scatter", action="store_true", help="Send scatter information via network")
|
PARSER.add_argument('--scatter', dest="send_scatter", action="store_true", help="Send scatter information via network")
|
||||||
PARSER.add_argument('--fft', dest="send_fft", action="store_true", help="Send fft information via network")
|
PARSER.add_argument('--fft', dest="send_fft", action="store_true", help="Send fft information via network")
|
||||||
PARSER.add_argument('--500hz', dest="low_bandwith_mode", action="store_true", help="Enable low bandwith mode ( 500 Hz only )")
|
PARSER.add_argument('--500hz', dest="low_bandwith_mode", action="store_true", help="Enable low bandwith mode ( 500 Hz only )")
|
||||||
PARSER.add_argument('--fsk', dest="enable_fsk", action="store_true", help="Enable FSK mode for ping, beacon and CQ")
|
PARSER.add_argument('--fsk', dest="enable_fsk", action="store_true", help="Enable FSK mode for ping, beacon and CQ")
|
||||||
PARSER.add_argument('--qrv', dest="enable_respond_to_cq", action="store_true", help="Enable sending a QRV frame if CQ received")
|
PARSER.add_argument('--qrv', dest="enable_respond_to_cq", action="store_true", help="Enable sending a QRV frame if CQ received")
|
||||||
PARSER.add_argument('--tuning_range_fmin', dest="tuning_range_fmin", choices=[-50.0, -100.0, -150.0, -200.0, -250.0], default=-50.0, help="Tuning range fmin", type=float)
|
PARSER.add_argument('--tuning_range_fmin', dest="tuning_range_fmin", choices=[-50.0, -100.0, -150.0, -200.0, -250.0], default=-50.0, help="Tuning range fmin", type=float)
|
||||||
PARSER.add_argument('--tuning_range_fmax', dest="tuning_range_fmax", choices=[50.0, 100.0, 150.0, 200.0, 250.0], default=50.0, help="Tuning range fmax", type=float)
|
PARSER.add_argument('--tuning_range_fmax', dest="tuning_range_fmax", choices=[50.0, 100.0, 150.0, 200.0, 250.0], default=50.0, help="Tuning range fmax", type=float)
|
||||||
PARSER.add_argument('--tx-audio-level', dest="tx_audio_level", default=50, help="Set the tx audio level at an early stage", type=int)
|
PARSER.add_argument('--tx-audio-level', dest="tx_audio_level", default=50, help="Set the tx audio level at an early stage", type=int)
|
||||||
|
|
||||||
|
|
||||||
ARGS = PARSER.parse_args()
|
ARGS = PARSER.parse_args()
|
||||||
|
|
||||||
# additional step for beeing sure our callsign is correctly
|
# additional step for beeing sure our callsign is correctly
|
||||||
|
@ -84,10 +84,10 @@ if __name__ == '__main__':
|
||||||
mycallsign = bytes(ARGS.mycall.upper(), 'utf-8')
|
mycallsign = bytes(ARGS.mycall.upper(), 'utf-8')
|
||||||
mycallsign = helpers.callsign_to_bytes(mycallsign)
|
mycallsign = helpers.callsign_to_bytes(mycallsign)
|
||||||
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign)
|
static.MYCALLSIGN = helpers.bytes_to_callsign(mycallsign)
|
||||||
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
static.MYCALLSIGN_CRC = helpers.get_crc_24(static.MYCALLSIGN)
|
||||||
|
|
||||||
static.SSID_LIST = ARGS.ssid_list
|
static.SSID_LIST = ARGS.ssid_list
|
||||||
|
|
||||||
static.MYGRID = bytes(ARGS.mygrid, 'utf-8')
|
static.MYGRID = bytes(ARGS.mygrid, 'utf-8')
|
||||||
static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device
|
static.AUDIO_INPUT_DEVICE = ARGS.audio_input_device
|
||||||
static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device
|
static.AUDIO_OUTPUT_DEVICE = ARGS.audio_output_device
|
||||||
|
@ -105,40 +105,40 @@ if __name__ == '__main__':
|
||||||
static.HAMLIB_RGICTLD_PORT = str(ARGS.rigctld_port)
|
static.HAMLIB_RGICTLD_PORT = str(ARGS.rigctld_port)
|
||||||
static.ENABLE_SCATTER = ARGS.send_scatter
|
static.ENABLE_SCATTER = ARGS.send_scatter
|
||||||
static.ENABLE_FFT = ARGS.send_fft
|
static.ENABLE_FFT = ARGS.send_fft
|
||||||
static.ENABLE_FSK = ARGS.enable_fsk
|
static.ENABLE_FSK = ARGS.enable_fsk
|
||||||
static.LOW_BANDWITH_MODE = ARGS.low_bandwith_mode
|
static.LOW_BANDWITH_MODE = ARGS.low_bandwith_mode
|
||||||
static.TUNING_RANGE_FMIN = ARGS.tuning_range_fmin
|
static.TUNING_RANGE_FMIN = ARGS.tuning_range_fmin
|
||||||
static.TUNING_RANGE_FMAX = ARGS.tuning_range_fmax
|
static.TUNING_RANGE_FMAX = ARGS.tuning_range_fmax
|
||||||
static.TX_AUDIO_LEVEL = ARGS.tx_audio_level
|
static.TX_AUDIO_LEVEL = ARGS.tx_audio_level
|
||||||
static.RESPOND_TO_CQ = ARGS.enable_respond_to_cq
|
static.RESPOND_TO_CQ = ARGS.enable_respond_to_cq
|
||||||
|
|
||||||
# we need to wait until we got all parameters from argparse first before we can load the other modules
|
# we need to wait until we got all parameters from argparse first before we can load the other modules
|
||||||
import sock
|
import sock
|
||||||
|
|
||||||
# config logging
|
# config logging
|
||||||
try:
|
try:
|
||||||
if sys.platform == 'linux':
|
if sys.platform == 'linux':
|
||||||
logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'tnc'
|
logging_path = os.getenv("HOME") + '/.config/' + 'FreeDATA/' + 'tnc'
|
||||||
|
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'tnc'
|
logging_path = os.getenv("HOME") + '/Library/' + 'Application Support/' + 'FreeDATA/' + 'tnc'
|
||||||
|
|
||||||
if sys.platform == 'win32' or sys.platform == 'win64':
|
if sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'tnc'
|
logging_path = os.getenv('APPDATA') + '/' + 'FreeDATA/' + 'tnc'
|
||||||
|
|
||||||
if not os.path.exists(logging_path):
|
if not os.path.exists(logging_path):
|
||||||
os.makedirs(logging_path)
|
os.makedirs(logging_path)
|
||||||
log_handler.setup_logging(logging_path)
|
log_handler.setup_logging(logging_path)
|
||||||
except:
|
except:
|
||||||
structlog.get_logger("structlog").error("[DMN] logger init error")
|
structlog.get_logger("structlog").error("[DMN] logger init error")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
structlog.get_logger("structlog").info("[TNC] Starting FreeDATA", author="DJ2LS", year="2022", version=static.VERSION)
|
structlog.get_logger("structlog").info("[TNC] Starting FreeDATA", author="DJ2LS", year="2022", version=static.VERSION)
|
||||||
|
|
||||||
# start data handler
|
# start data handler
|
||||||
data_handler.DATA()
|
data_handler.DATA()
|
||||||
|
|
||||||
# start modem
|
# start modem
|
||||||
modem = modem.RF()
|
modem = modem.RF()
|
||||||
|
|
||||||
|
|
413
tnc/modem.py
413
tnc/modem.py
|
@ -45,10 +45,10 @@ class RF():
|
||||||
""" """
|
""" """
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.sampler_avg = 0
|
self.sampler_avg = 0
|
||||||
self.buffer_avg = 0
|
self.buffer_avg = 0
|
||||||
|
|
||||||
|
|
||||||
self.AUDIO_SAMPLE_RATE_RX = 48000
|
self.AUDIO_SAMPLE_RATE_RX = 48000
|
||||||
self.AUDIO_SAMPLE_RATE_TX = 48000
|
self.AUDIO_SAMPLE_RATE_TX = 48000
|
||||||
|
@ -57,15 +57,15 @@ class RF():
|
||||||
self.AUDIO_FRAMES_PER_BUFFER_TX = 2400*2 #8192 Lets to some tests with very small chunks for TX
|
self.AUDIO_FRAMES_PER_BUFFER_TX = 2400*2 #8192 Lets to some tests with very small chunks for TX
|
||||||
self.AUDIO_CHUNKS = 48 #8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) #48
|
self.AUDIO_CHUNKS = 48 #8 * (self.AUDIO_SAMPLE_RATE_RX/self.MODEM_SAMPLE_RATE) #48
|
||||||
self.AUDIO_CHANNELS = 1
|
self.AUDIO_CHANNELS = 1
|
||||||
|
|
||||||
# locking state for mod out so buffer will be filled before we can use it
|
# locking state for mod out so buffer will be filled before we can use it
|
||||||
# https://github.com/DJ2LS/FreeDATA/issues/127
|
# https://github.com/DJ2LS/FreeDATA/issues/127
|
||||||
# https://github.com/DJ2LS/FreeDATA/issues/99
|
# https://github.com/DJ2LS/FreeDATA/issues/99
|
||||||
self.mod_out_locked = True
|
self.mod_out_locked = True
|
||||||
|
|
||||||
# make sure our resampler will work
|
# make sure our resampler will work
|
||||||
assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48
|
assert (self.AUDIO_SAMPLE_RATE_RX / self.MODEM_SAMPLE_RATE) == codec2.api.FDMDV_OS_48
|
||||||
|
|
||||||
# small hack for initializing codec2 via codec2.py module
|
# small hack for initializing codec2 via codec2.py module
|
||||||
# TODO: we need to change the entire modem module to integrate codec2 module
|
# TODO: we need to change the entire modem module to integrate codec2 module
|
||||||
self.c_lib = codec2.api
|
self.c_lib = codec2.api
|
||||||
|
@ -76,11 +76,11 @@ class RF():
|
||||||
|
|
||||||
# init FIFO queue to store modulation out in
|
# init FIFO queue to store modulation out in
|
||||||
self.modoutqueue = deque()
|
self.modoutqueue = deque()
|
||||||
|
|
||||||
# define fft_data buffer
|
# define fft_data buffer
|
||||||
self.fft_data = bytes()
|
self.fft_data = bytes()
|
||||||
|
|
||||||
# open codec2 instance
|
# open codec2 instance
|
||||||
self.datac0_freedv = cast(codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), c_void_p)
|
self.datac0_freedv = cast(codec2.api.freedv_open(codec2.api.FREEDV_MODE_DATAC0), c_void_p)
|
||||||
self.c_lib.freedv_set_tuning_range(self.datac0_freedv, c_float(static.TUNING_RANGE_FMIN), c_float(static.TUNING_RANGE_FMAX))
|
self.c_lib.freedv_set_tuning_range(self.datac0_freedv, c_float(static.TUNING_RANGE_FMIN), c_float(static.TUNING_RANGE_FMAX))
|
||||||
self.datac0_bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(self.datac0_freedv)/8)
|
self.datac0_bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(self.datac0_freedv)/8)
|
||||||
|
@ -120,70 +120,54 @@ class RF():
|
||||||
#codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0,1)
|
#codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0,1)
|
||||||
self.fsk_ldpc_buffer_1 = codec2.audio_buffer(self.AUDIO_FRAMES_PER_BUFFER_RX)
|
self.fsk_ldpc_buffer_1 = codec2.audio_buffer(self.AUDIO_FRAMES_PER_BUFFER_RX)
|
||||||
|
|
||||||
# initial nin values
|
# initial nin values
|
||||||
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
self.datac0_nin = codec2.api.freedv_nin(self.datac0_freedv)
|
||||||
self.datac1_nin = codec2.api.freedv_nin(self.datac1_freedv)
|
self.datac1_nin = codec2.api.freedv_nin(self.datac1_freedv)
|
||||||
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
||||||
self.fsk_ldpc_nin_0 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_0)
|
self.fsk_ldpc_nin_0 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_0)
|
||||||
self.fsk_ldpc_nin_1 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_1)
|
self.fsk_ldpc_nin_1 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_1)
|
||||||
# --------------------------------------------CREATE PYAUDIO INSTANCE
|
# --------------------------------------------CREATE PYAUDIO INSTANCE
|
||||||
|
if not TESTMODE:
|
||||||
'''
|
try:
|
||||||
try:
|
|
||||||
# we need to "try" this, because sometimes libasound.so isn't in the default place
|
self.stream = sd.RawStream(channels=1, dtype='int16', callback=self.callback, device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), samplerate = self.AUDIO_SAMPLE_RATE_RX, blocksize=4800)
|
||||||
# try to supress error messages
|
atexit.register(self.stream.stop)
|
||||||
with audio.noalsaerr(): # https://github.com/DJ2LS/FreeDATA/issues/22
|
structlog.get_logger("structlog").info("opened audio devices")
|
||||||
self.p = audio.pyaudio.PyAudio()
|
|
||||||
# else do it the default way
|
except Exception as e:
|
||||||
except:
|
structlog.get_logger("structlog").error("can't open audio device. Exit", e=e)
|
||||||
self.p = audio.pyaudio.PyAudio()
|
os._exit(1)
|
||||||
atexit.register(self.p.terminate)
|
|
||||||
|
try:
|
||||||
# --------------------------------------------OPEN RX AUDIO CHANNEL
|
structlog.get_logger("structlog").debug("[TNC] starting pyaudio callback")
|
||||||
# optional auto selection of loopback device if using in testmode
|
#self.audio_stream.start_stream()
|
||||||
if static.AUDIO_INPUT_DEVICE == -2:
|
self.stream.start()
|
||||||
loopback_list = []
|
|
||||||
for dev in range(0,self.p.get_device_count()):
|
except Exception as e:
|
||||||
if 'Loopback: PCM' in self.p.get_device_info_by_index(dev)["name"]:
|
structlog.get_logger("structlog").error("[TNC] starting pyaudio callback failed", e=e)
|
||||||
loopback_list.append(dev)
|
|
||||||
if len(loopback_list) >= 2:
|
else:
|
||||||
static.AUDIO_INPUT_DEVICE = loopback_list[0] #0 = RX
|
|
||||||
static.AUDIO_OUTPUT_DEVICE = loopback_list[1] #1 = TX
|
# create a stream object for simulating audio stream
|
||||||
print(f"loopback_list rx: {loopback_list}", file=sys.stderr)
|
class Object(object):
|
||||||
|
pass
|
||||||
'''
|
self.stream = Object()
|
||||||
try:
|
self.stream.active = True
|
||||||
'''
|
|
||||||
self.audio_stream = self.p.open(format=audio.pyaudio.paInt16,
|
# create mkfifo buffer
|
||||||
channels=self.AUDIO_CHANNELS,
|
try:
|
||||||
rate=self.AUDIO_SAMPLE_RATE_RX,
|
|
||||||
frames_per_buffer=self.AUDIO_FRAMES_PER_BUFFER_RX,
|
os.mkfifo(RXCHANNEL)
|
||||||
input=True,
|
os.mkfifo(TXCHANNEL)
|
||||||
output=True,
|
except:
|
||||||
input_device_index=static.AUDIO_INPUT_DEVICE,
|
pass
|
||||||
output_device_index=static.AUDIO_OUTPUT_DEVICE,
|
|
||||||
stream_callback=self.audio_callback
|
mkfifo_write_callback_thread = threading.Thread(target=self.mkfifo_write_callback, name="MKFIFO WRITE CALLBACK THREAD",daemon=True)
|
||||||
)
|
mkfifo_write_callback_thread.start()
|
||||||
'''
|
|
||||||
|
mkfifo_read_callback_thread = threading.Thread(target=self.mkfifo_read_callback, name="MKFIFO READ CALLBACK THREAD",daemon=True)
|
||||||
self.stream = sd.RawStream(channels=1, dtype='int16', callback=self.callback, device=(static.AUDIO_INPUT_DEVICE, static.AUDIO_OUTPUT_DEVICE), samplerate = self.AUDIO_SAMPLE_RATE_RX, blocksize=4800)
|
mkfifo_read_callback_thread.start()
|
||||||
|
|
||||||
|
|
||||||
atexit.register(self.stream.stop)
|
|
||||||
|
|
||||||
structlog.get_logger("structlog").info("opened audio devices")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
structlog.get_logger("structlog").error("can't open audio device. Exit", e=e)
|
|
||||||
os._exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
structlog.get_logger("structlog").debug("[TNC] starting pyaudio callback")
|
|
||||||
#self.audio_stream.start_stream()
|
|
||||||
self.stream.start()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
structlog.get_logger("structlog").error("[TNC] starting pyaudio callback failed", e=e)
|
|
||||||
|
|
||||||
# --------------------------------------------INIT AND OPEN HAMLIB
|
# --------------------------------------------INIT AND OPEN HAMLIB
|
||||||
# check how we want to control the radio
|
# check how we want to control the radio
|
||||||
|
@ -196,9 +180,9 @@ class RF():
|
||||||
elif static.HAMLIB_RADIOCONTROL == 'disabled':
|
elif static.HAMLIB_RADIOCONTROL == 'disabled':
|
||||||
import rigdummy as rig
|
import rigdummy as rig
|
||||||
else:
|
else:
|
||||||
import rigdummy as rig
|
import rigdummy as rig
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.hamlib = rig.radio()
|
self.hamlib = rig.radio()
|
||||||
self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE, rigctld_ip = static.HAMLIB_RGICTLD_IP, rigctld_port = static.HAMLIB_RGICTLD_PORT)
|
self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE, rigctld_ip = static.HAMLIB_RGICTLD_IP, rigctld_port = static.HAMLIB_RGICTLD_PORT)
|
||||||
|
|
||||||
|
@ -206,52 +190,101 @@ class RF():
|
||||||
if static.ENABLE_FFT:
|
if static.ENABLE_FFT:
|
||||||
fft_thread = threading.Thread(target=self.calculate_fft, name="FFT_THREAD" ,daemon=True)
|
fft_thread = threading.Thread(target=self.calculate_fft, name="FFT_THREAD" ,daemon=True)
|
||||||
fft_thread.start()
|
fft_thread.start()
|
||||||
|
|
||||||
audio_thread_datac0 = threading.Thread(target=self.audio_datac0, name="AUDIO_THREAD DATAC0",daemon=True)
|
audio_thread_datac0 = threading.Thread(target=self.audio_datac0, name="AUDIO_THREAD DATAC0",daemon=True)
|
||||||
audio_thread_datac0.start()
|
audio_thread_datac0.start()
|
||||||
|
|
||||||
audio_thread_datac1 = threading.Thread(target=self.audio_datac1, name="AUDIO_THREAD DATAC1",daemon=True)
|
audio_thread_datac1 = threading.Thread(target=self.audio_datac1, name="AUDIO_THREAD DATAC1",daemon=True)
|
||||||
audio_thread_datac1.start()
|
audio_thread_datac1.start()
|
||||||
|
|
||||||
audio_thread_datac3 = threading.Thread(target=self.audio_datac3, name="AUDIO_THREAD DATAC3",daemon=True)
|
audio_thread_datac3 = threading.Thread(target=self.audio_datac3, name="AUDIO_THREAD DATAC3",daemon=True)
|
||||||
audio_thread_datac3.start()
|
audio_thread_datac3.start()
|
||||||
|
|
||||||
if static.ENABLE_FSK:
|
if static.ENABLE_FSK:
|
||||||
audio_thread_fsk_ldpc0 = threading.Thread(target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0",daemon=True)
|
audio_thread_fsk_ldpc0 = threading.Thread(target=self.audio_fsk_ldpc_0, name="AUDIO_THREAD FSK LDPC0",daemon=True)
|
||||||
audio_thread_fsk_ldpc0.start()
|
audio_thread_fsk_ldpc0.start()
|
||||||
|
|
||||||
audio_thread_fsk_ldpc1 = threading.Thread(target=self.audio_fsk_ldpc_1, name="AUDIO_THREAD FSK LDPC1",daemon=True)
|
audio_thread_fsk_ldpc1 = threading.Thread(target=self.audio_fsk_ldpc_1, name="AUDIO_THREAD FSK LDPC1",daemon=True)
|
||||||
audio_thread_fsk_ldpc1.start()
|
audio_thread_fsk_ldpc1.start()
|
||||||
|
|
||||||
hamlib_thread = threading.Thread(target=self.update_rig_data, name="HAMLIB_THREAD",daemon=True)
|
hamlib_thread = threading.Thread(target=self.update_rig_data, name="HAMLIB_THREAD",daemon=True)
|
||||||
hamlib_thread.start()
|
hamlib_thread.start()
|
||||||
|
|
||||||
worker_received = threading.Thread(target=self.worker_received, name="WORKER_THREAD",daemon=True)
|
worker_received = threading.Thread(target=self.worker_received, name="WORKER_THREAD",daemon=True)
|
||||||
worker_received.start()
|
worker_received.start()
|
||||||
|
|
||||||
worker_transmit = threading.Thread(target=self.worker_transmit, name="WORKER_THREAD",daemon=True)
|
worker_transmit = threading.Thread(target=self.worker_transmit, name="WORKER_THREAD",daemon=True)
|
||||||
worker_transmit.start()
|
worker_transmit.start()
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------------------------------------
|
||||||
|
def mkfifo_read_callback(self):
|
||||||
|
while 1:
|
||||||
|
|
||||||
|
time.sleep(0.01)
|
||||||
|
# -----read
|
||||||
|
data_in48k = bytes()
|
||||||
|
with open(RXCHANNEL, 'rb') as fifo:
|
||||||
|
for line in fifo:
|
||||||
|
|
||||||
|
data_in48k += line
|
||||||
|
|
||||||
|
while len(data_in48k) >= 48:
|
||||||
|
x = np.frombuffer(data_in48k[:48], dtype=np.int16)
|
||||||
|
x = self.resampler.resample48_to_8(x)
|
||||||
|
data_in48k = data_in48k[48:]
|
||||||
|
|
||||||
|
length_x = len(x)
|
||||||
|
if not self.datac0_buffer.nbuffer+length_x > self.datac0_buffer.size:
|
||||||
|
self.datac0_buffer.push(x)
|
||||||
|
|
||||||
|
if not self.datac1_buffer.nbuffer+length_x > self.datac1_buffer.size:
|
||||||
|
if RECEIVE_DATAC1:
|
||||||
|
self.datac1_buffer.push(x)
|
||||||
|
|
||||||
|
if not self.datac3_buffer.nbuffer+length_x > self.datac3_buffer.size:
|
||||||
|
if RECEIVE_DATAC3:
|
||||||
|
self.datac3_buffer.push(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def mkfifo_write_callback(self):
|
||||||
|
while 1:
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
# -----write
|
||||||
|
if len(self.modoutqueue) <= 0 or self.mod_out_locked:
|
||||||
|
#data_out48k = np.zeros(self.AUDIO_FRAMES_PER_BUFFER_RX, dtype=np.int16)
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
data_out48k = self.modoutqueue.popleft()
|
||||||
|
#print(len(data_out48k))
|
||||||
|
|
||||||
|
fifo_write = open(TXCHANNEL, 'wb')
|
||||||
|
fifo_write.write(data_out48k)
|
||||||
|
fifo_write.flush()
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------------
|
||||||
#def audio_callback(self, data_in48k, frame_count, time_info, status):
|
#def audio_callback(self, data_in48k, frame_count, time_info, status):
|
||||||
def callback(self, data_in48k, outdata, frames, time, status):
|
def callback(self, data_in48k, outdata, frames, time, status):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data_in48k:
|
data_in48k:
|
||||||
frame_count:
|
frame_count:
|
||||||
time_info:
|
time_info:
|
||||||
status:
|
status:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
x = np.frombuffer(data_in48k, dtype=np.int16)
|
x = np.frombuffer(data_in48k, dtype=np.int16)
|
||||||
x = self.resampler.resample48_to_8(x)
|
x = self.resampler.resample48_to_8(x)
|
||||||
|
|
||||||
length_x = len(x)
|
length_x = len(x)
|
||||||
|
|
||||||
# avoid decoding when transmitting to reduce CPU
|
# avoid decoding when transmitting to reduce CPU
|
||||||
if not static.TRANSMITTING:
|
if not static.TRANSMITTING:
|
||||||
# avoid buffer overflow by filling only if buffer not full
|
# avoid buffer overflow by filling only if buffer not full
|
||||||
|
@ -259,14 +292,14 @@ class RF():
|
||||||
self.datac0_buffer.push(x)
|
self.datac0_buffer.push(x)
|
||||||
else:
|
else:
|
||||||
static.BUFFER_OVERFLOW_COUNTER[0] += 1
|
static.BUFFER_OVERFLOW_COUNTER[0] += 1
|
||||||
|
|
||||||
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
||||||
if not self.datac1_buffer.nbuffer+length_x > self.datac1_buffer.size:
|
if not self.datac1_buffer.nbuffer+length_x > self.datac1_buffer.size:
|
||||||
if RECEIVE_DATAC1:
|
if RECEIVE_DATAC1:
|
||||||
self.datac1_buffer.push(x)
|
self.datac1_buffer.push(x)
|
||||||
else:
|
else:
|
||||||
static.BUFFER_OVERFLOW_COUNTER[1] += 1
|
static.BUFFER_OVERFLOW_COUNTER[1] += 1
|
||||||
|
|
||||||
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
||||||
if not self.datac3_buffer.nbuffer+length_x > self.datac3_buffer.size:
|
if not self.datac3_buffer.nbuffer+length_x > self.datac3_buffer.size:
|
||||||
if RECEIVE_DATAC3:
|
if RECEIVE_DATAC3:
|
||||||
|
@ -276,29 +309,29 @@ class RF():
|
||||||
|
|
||||||
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
||||||
if not self.fsk_ldpc_buffer_0.nbuffer+length_x > self.fsk_ldpc_buffer_0.size:
|
if not self.fsk_ldpc_buffer_0.nbuffer+length_x > self.fsk_ldpc_buffer_0.size:
|
||||||
if static.ENABLE_FSK:
|
if static.ENABLE_FSK:
|
||||||
self.fsk_ldpc_buffer_0.push(x)
|
self.fsk_ldpc_buffer_0.push(x)
|
||||||
else:
|
else:
|
||||||
static.BUFFER_OVERFLOW_COUNTER[3] += 1
|
static.BUFFER_OVERFLOW_COUNTER[3] += 1
|
||||||
|
|
||||||
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
# avoid buffer overflow by filling only if buffer not full and selected datachannel mode
|
||||||
if not self.fsk_ldpc_buffer_1.nbuffer+length_x > self.fsk_ldpc_buffer_1.size:
|
if not self.fsk_ldpc_buffer_1.nbuffer+length_x > self.fsk_ldpc_buffer_1.size:
|
||||||
if RECEIVE_FSK_LDPC_1 and static.ENABLE_FSK:
|
if RECEIVE_FSK_LDPC_1 and static.ENABLE_FSK:
|
||||||
self.fsk_ldpc_buffer_1.push(x)
|
self.fsk_ldpc_buffer_1.push(x)
|
||||||
else:
|
else:
|
||||||
static.BUFFER_OVERFLOW_COUNTER[4] += 1
|
static.BUFFER_OVERFLOW_COUNTER[4] += 1
|
||||||
|
|
||||||
if len(self.modoutqueue) <= 0 or self.mod_out_locked:
|
if len(self.modoutqueue) <= 0 or self.mod_out_locked:
|
||||||
#if not self.modoutqueue or self.mod_out_locked:
|
#if not self.modoutqueue or self.mod_out_locked:
|
||||||
data_out48k = np.zeros(frames, dtype=np.int16)
|
data_out48k = np.zeros(frames, dtype=np.int16)
|
||||||
self.fft_data = x
|
self.fft_data = x
|
||||||
|
|
||||||
else:
|
else:
|
||||||
data_out48k = self.modoutqueue.popleft()
|
data_out48k = self.modoutqueue.popleft()
|
||||||
self.fft_data = data_out48k
|
self.fft_data = data_out48k
|
||||||
|
|
||||||
try:
|
try:
|
||||||
outdata[:] = data_out48k[:frames]
|
outdata[:] = data_out48k[:frames]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
@ -306,14 +339,14 @@ class RF():
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def transmit(self, mode, repeats, repeat_delay, frames):
|
def transmit(self, mode, repeats, repeat_delay, frames):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
repeats:
|
repeats:
|
||||||
repeat_delay:
|
repeat_delay:
|
||||||
frames:
|
frames:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -324,19 +357,19 @@ class RF():
|
||||||
jsondata = {"ptt":"True"}
|
jsondata = {"ptt":"True"}
|
||||||
data_out = json.dumps(jsondata)
|
data_out = json.dumps(jsondata)
|
||||||
sock.SOCKET_QUEUE.put(data_out)
|
sock.SOCKET_QUEUE.put(data_out)
|
||||||
|
|
||||||
|
|
||||||
# open codec2 instance
|
# open codec2 instance
|
||||||
self.MODE = mode
|
self.MODE = mode
|
||||||
if self.MODE == 'FSK_LDPC_0' or self.MODE == 200:
|
if self.MODE == 'FSK_LDPC_0' or self.MODE == 200:
|
||||||
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), c_void_p)
|
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), c_void_p)
|
||||||
elif self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
elif self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
||||||
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), c_void_p)
|
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), c_void_p)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
freedv = cast(codec2.api.freedv_open(self.MODE), c_void_p)
|
freedv = cast(codec2.api.freedv_open(self.MODE), c_void_p)
|
||||||
|
|
||||||
|
|
||||||
# get number of bytes per frame for mode
|
# get number of bytes per frame for mode
|
||||||
bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(freedv)/8)
|
bytes_per_frame = int(codec2.api.freedv_get_bits_per_modem_frame(freedv)/8)
|
||||||
payload_bytes_per_frame = bytes_per_frame -2
|
payload_bytes_per_frame = bytes_per_frame -2
|
||||||
|
@ -356,12 +389,12 @@ class RF():
|
||||||
data_delay_mseconds = 0 #miliseconds
|
data_delay_mseconds = 0 #miliseconds
|
||||||
data_delay = int(self.MODEM_SAMPLE_RATE*(data_delay_mseconds/1000))
|
data_delay = int(self.MODEM_SAMPLE_RATE*(data_delay_mseconds/1000))
|
||||||
mod_out_silence = create_string_buffer(data_delay*2)
|
mod_out_silence = create_string_buffer(data_delay*2)
|
||||||
txbuffer = bytes(mod_out_silence)
|
txbuffer = bytes(mod_out_silence)
|
||||||
|
|
||||||
structlog.get_logger("structlog").debug("TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame)
|
structlog.get_logger("structlog").debug("TRANSMIT", mode=self.MODE, payload=payload_bytes_per_frame)
|
||||||
|
|
||||||
for i in range(0,repeats):
|
for i in range(0,repeats):
|
||||||
# codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing
|
# codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing
|
||||||
if not self.MODE == 'FSK_LDPC_0' or self.MODE == 200 or self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
if not self.MODE == 'FSK_LDPC_0' or self.MODE == 200 or self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
||||||
# write preamble to txbuffer
|
# write preamble to txbuffer
|
||||||
codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble)
|
codec2.api.freedv_rawdatapreambletx(freedv, mod_out_preamble)
|
||||||
|
@ -372,28 +405,28 @@ class RF():
|
||||||
buffer = bytearray(payload_bytes_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
|
buffer = bytearray(payload_bytes_per_frame) # use this if CRC16 checksum is required ( DATA1-3)
|
||||||
buffer[:len(frames[n])] = frames[n] # set buffersize to length of data which will be send
|
buffer[:len(frames[n])] = frames[n] # set buffersize to length of data which will be send
|
||||||
|
|
||||||
# create crc for data frame - we are using the crc function shipped with codec2 to avoid
|
# create crc for data frame - we are using the crc function shipped with codec2 to avoid
|
||||||
# crc algorithm incompatibilities
|
# crc algorithm incompatibilities
|
||||||
crc = ctypes.c_ushort(codec2.api.freedv_gen_crc16(bytes(buffer), payload_bytes_per_frame)) # generate CRC16
|
crc = ctypes.c_ushort(codec2.api.freedv_gen_crc16(bytes(buffer), payload_bytes_per_frame)) # generate CRC16
|
||||||
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string
|
crc = crc.value.to_bytes(2, byteorder='big') # convert crc to 2 byte hex string
|
||||||
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)
|
||||||
codec2.api.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and save it into mod_out pointer
|
codec2.api.freedv_rawdatatx(freedv,mod_out,data) # modulate DATA and save it into mod_out pointer
|
||||||
txbuffer += bytes(mod_out)
|
txbuffer += bytes(mod_out)
|
||||||
|
|
||||||
|
|
||||||
# codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing
|
# codec2 fsk preamble may be broken - at least it sounds like that so we are disabling it for testing
|
||||||
if not self.MODE == 'FSK_LDPC_0' or self.MODE == 200 or self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
if not self.MODE == 'FSK_LDPC_0' or self.MODE == 200 or self.MODE == 'FSK_LDPC_1' or self.MODE == 201:
|
||||||
# write preamble to txbuffer
|
# write preamble to txbuffer
|
||||||
codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble)
|
codec2.api.freedv_rawdatapostambletx(freedv, mod_out_postamble)
|
||||||
txbuffer += bytes(mod_out_postamble)
|
txbuffer += bytes(mod_out_postamble)
|
||||||
# append postamble to txbuffer
|
# append postamble to txbuffer
|
||||||
# add delay to end of frames
|
# add delay to end of frames
|
||||||
samples_delay = int(self.MODEM_SAMPLE_RATE*(repeat_delay/1000))
|
samples_delay = int(self.MODEM_SAMPLE_RATE*(repeat_delay/1000))
|
||||||
mod_out_silence = create_string_buffer(samples_delay*2)
|
mod_out_silence = create_string_buffer(samples_delay*2)
|
||||||
txbuffer += bytes(mod_out_silence)
|
txbuffer += bytes(mod_out_silence)
|
||||||
|
|
||||||
# resample up to 48k (resampler works on np.int16)
|
# resample up to 48k (resampler works on np.int16)
|
||||||
x = np.frombuffer(txbuffer, dtype=np.int16)
|
x = np.frombuffer(txbuffer, dtype=np.int16)
|
||||||
x = set_audio_volume(x, static.TX_AUDIO_LEVEL)
|
x = set_audio_volume(x, static.TX_AUDIO_LEVEL)
|
||||||
|
@ -403,11 +436,11 @@ class RF():
|
||||||
# explicitly lock our usage of mod_out_queue if needed
|
# explicitly lock our usage of mod_out_queue if needed
|
||||||
# deaktivated for testing purposes
|
# deaktivated for testing purposes
|
||||||
self.mod_out_locked = False
|
self.mod_out_locked = False
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------
|
# -------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
chunk_length = self.AUDIO_FRAMES_PER_BUFFER_TX #4800
|
chunk_length = self.AUDIO_FRAMES_PER_BUFFER_TX #4800
|
||||||
|
@ -422,35 +455,35 @@ class RF():
|
||||||
#structlog.get_logger("structlog").debug("[TNC] mod out shorter than audio buffer", delta=delta)
|
#structlog.get_logger("structlog").debug("[TNC] mod out shorter than audio buffer", delta=delta)
|
||||||
self.modoutqueue.append(c)
|
self.modoutqueue.append(c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Release our mod_out_lock so we can use the queue
|
|
||||||
|
# Release our mod_out_lock so we can use the queue
|
||||||
self.mod_out_locked = False
|
self.mod_out_locked = False
|
||||||
|
|
||||||
while self.modoutqueue:
|
while self.modoutqueue:
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
static.PTT_STATE = self.hamlib.set_ptt(False)
|
static.PTT_STATE = self.hamlib.set_ptt(False)
|
||||||
|
|
||||||
# push ptt state to socket stream
|
# push ptt state to socket stream
|
||||||
jsondata = {"ptt":"False"}
|
jsondata = {"ptt":"False"}
|
||||||
data_out = json.dumps(jsondata)
|
data_out = json.dumps(jsondata)
|
||||||
sock.SOCKET_QUEUE.put(data_out)
|
sock.SOCKET_QUEUE.put(data_out)
|
||||||
|
|
||||||
# after processing we want to set the locking state back to true to be prepared for next transmission
|
# after processing we want to set the locking state back to true to be prepared for next transmission
|
||||||
self.mod_out_locked = True
|
self.mod_out_locked = True
|
||||||
|
|
||||||
self.c_lib.freedv_close(freedv)
|
self.c_lib.freedv_close(freedv)
|
||||||
self.modem_transmit_queue.task_done()
|
self.modem_transmit_queue.task_done()
|
||||||
static.TRANSMITTING = False
|
static.TRANSMITTING = False
|
||||||
threading.Event().set()
|
threading.Event().set()
|
||||||
|
|
||||||
def audio_datac0(self):
|
def audio_datac0(self):
|
||||||
""" """
|
""" """
|
||||||
nbytes_datac0 = 0
|
nbytes_datac0 = 0
|
||||||
while self.stream.active:
|
while self.stream.active:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
while self.datac0_buffer.nbuffer >= self.datac0_nin:
|
while self.datac0_buffer.nbuffer >= self.datac0_nin:
|
||||||
# demodulate audio
|
# demodulate audio
|
||||||
nbytes_datac0 = codec2.api.freedv_rawdatarx(self.datac0_freedv, self.datac0_bytes_out, self.datac0_buffer.buffer.ctypes)
|
nbytes_datac0 = codec2.api.freedv_rawdatarx(self.datac0_freedv, self.datac0_bytes_out, self.datac0_buffer.buffer.ctypes)
|
||||||
self.datac0_buffer.pop(self.datac0_nin)
|
self.datac0_buffer.pop(self.datac0_nin)
|
||||||
|
@ -474,66 +507,66 @@ class RF():
|
||||||
self.modem_received_queue.put([self.datac1_bytes_out, self.datac1_freedv ,self.datac1_bytes_per_frame])
|
self.modem_received_queue.put([self.datac1_bytes_out, self.datac1_freedv ,self.datac1_bytes_per_frame])
|
||||||
#self.get_scatter(self.datac1_freedv)
|
#self.get_scatter(self.datac1_freedv)
|
||||||
self.calculate_snr(self.datac1_freedv)
|
self.calculate_snr(self.datac1_freedv)
|
||||||
|
|
||||||
def audio_datac3(self):
|
def audio_datac3(self):
|
||||||
""" """
|
""" """
|
||||||
nbytes_datac3 = 0
|
nbytes_datac3 = 0
|
||||||
while self.stream.active:
|
while self.stream.active:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
while self.datac3_buffer.nbuffer >= self.datac3_nin:
|
while self.datac3_buffer.nbuffer >= self.datac3_nin:
|
||||||
# demodulate audio
|
# demodulate audio
|
||||||
nbytes_datac3 = codec2.api.freedv_rawdatarx(self.datac3_freedv, self.datac3_bytes_out, self.datac3_buffer.buffer.ctypes)
|
nbytes_datac3 = codec2.api.freedv_rawdatarx(self.datac3_freedv, self.datac3_bytes_out, self.datac3_buffer.buffer.ctypes)
|
||||||
self.datac3_buffer.pop(self.datac3_nin)
|
self.datac3_buffer.pop(self.datac3_nin)
|
||||||
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
self.datac3_nin = codec2.api.freedv_nin(self.datac3_freedv)
|
||||||
if nbytes_datac3 == self.datac3_bytes_per_frame:
|
if nbytes_datac3 == self.datac3_bytes_per_frame:
|
||||||
self.modem_received_queue.put([self.datac3_bytes_out, self.datac3_freedv ,self.datac3_bytes_per_frame])
|
self.modem_received_queue.put([self.datac3_bytes_out, self.datac3_freedv ,self.datac3_bytes_per_frame])
|
||||||
#self.get_scatter(self.datac3_freedv)
|
#self.get_scatter(self.datac3_freedv)
|
||||||
self.calculate_snr(self.datac3_freedv)
|
self.calculate_snr(self.datac3_freedv)
|
||||||
|
|
||||||
def audio_fsk_ldpc_0(self):
|
def audio_fsk_ldpc_0(self):
|
||||||
""" """
|
""" """
|
||||||
nbytes_fsk_ldpc_0 = 0
|
nbytes_fsk_ldpc_0 = 0
|
||||||
while self.stream.active and static.ENABLE_FSK:
|
while self.stream.active and static.ENABLE_FSK:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
while self.fsk_ldpc_buffer_0.nbuffer >= self.fsk_ldpc_nin_0:
|
while self.fsk_ldpc_buffer_0.nbuffer >= self.fsk_ldpc_nin_0:
|
||||||
# demodulate audio
|
# demodulate audio
|
||||||
nbytes_fsk_ldpc_0 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_buffer_0.buffer.ctypes)
|
nbytes_fsk_ldpc_0 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_0, self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_buffer_0.buffer.ctypes)
|
||||||
self.fsk_ldpc_buffer_0.pop(self.fsk_ldpc_nin_0)
|
self.fsk_ldpc_buffer_0.pop(self.fsk_ldpc_nin_0)
|
||||||
self.fsk_ldpc_nin_0 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_0)
|
self.fsk_ldpc_nin_0 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_0)
|
||||||
if nbytes_fsk_ldpc_0 == self.fsk_ldpc_bytes_per_frame_0:
|
if nbytes_fsk_ldpc_0 == self.fsk_ldpc_bytes_per_frame_0:
|
||||||
self.modem_received_queue.put([self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_freedv_0 ,self.fsk_ldpc_bytes_per_frame_0])
|
self.modem_received_queue.put([self.fsk_ldpc_bytes_out_0, self.fsk_ldpc_freedv_0 ,self.fsk_ldpc_bytes_per_frame_0])
|
||||||
#self.get_scatter(self.fsk_ldpc_freedv_0)
|
#self.get_scatter(self.fsk_ldpc_freedv_0)
|
||||||
self.calculate_snr(self.fsk_ldpc_freedv_0)
|
self.calculate_snr(self.fsk_ldpc_freedv_0)
|
||||||
|
|
||||||
def audio_fsk_ldpc_1(self):
|
def audio_fsk_ldpc_1(self):
|
||||||
""" """
|
""" """
|
||||||
nbytes_fsk_ldpc_1 = 0
|
nbytes_fsk_ldpc_1 = 0
|
||||||
while self.stream.active and static.ENABLE_FSK:
|
while self.stream.active and static.ENABLE_FSK:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
while self.fsk_ldpc_buffer_1.nbuffer >= self.fsk_ldpc_nin_1:
|
while self.fsk_ldpc_buffer_1.nbuffer >= self.fsk_ldpc_nin_1:
|
||||||
# demodulate audio
|
# demodulate audio
|
||||||
nbytes_fsk_ldpc_1 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_buffer_1.buffer.ctypes)
|
nbytes_fsk_ldpc_1 = codec2.api.freedv_rawdatarx(self.fsk_ldpc_freedv_1, self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_buffer_1.buffer.ctypes)
|
||||||
self.fsk_ldpc_buffer_1.pop(self.fsk_ldpc_nin_1)
|
self.fsk_ldpc_buffer_1.pop(self.fsk_ldpc_nin_1)
|
||||||
self.fsk_ldpc_nin_1 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_1)
|
self.fsk_ldpc_nin_1 = codec2.api.freedv_nin(self.fsk_ldpc_freedv_1)
|
||||||
if nbytes_fsk_ldpc_1 == self.fsk_ldpc_bytes_per_frame_1:
|
if nbytes_fsk_ldpc_1 == self.fsk_ldpc_bytes_per_frame_1:
|
||||||
self.modem_received_queue.put([self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_freedv_1 ,self.fsk_ldpc_bytes_per_frame_1])
|
self.modem_received_queue.put([self.fsk_ldpc_bytes_out_1, self.fsk_ldpc_freedv_1 ,self.fsk_ldpc_bytes_per_frame_1])
|
||||||
#self.get_scatter(self.fsk_ldpc_freedv_1)
|
#self.get_scatter(self.fsk_ldpc_freedv_1)
|
||||||
self.calculate_snr(self.fsk_ldpc_freedv_1)
|
self.calculate_snr(self.fsk_ldpc_freedv_1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# worker for FIFO queue for processing received frames
|
# worker for FIFO queue for processing received frames
|
||||||
def worker_transmit(self):
|
def worker_transmit(self):
|
||||||
""" """
|
""" """
|
||||||
while True:
|
while True:
|
||||||
data = self.modem_transmit_queue.get()
|
data = self.modem_transmit_queue.get()
|
||||||
|
|
||||||
self.transmit(mode=data[0], repeats=data[1], repeat_delay=data[2], frames=data[3])
|
|
||||||
#self.modem_transmit_queue.task_done()
|
|
||||||
|
|
||||||
|
self.transmit(mode=data[0], repeats=data[1], repeat_delay=data[2], frames=data[3])
|
||||||
|
#self.modem_transmit_queue.task_done()
|
||||||
# worker for FIFO queue for processing received frames
|
|
||||||
|
|
||||||
|
|
||||||
|
# worker for FIFO queue for processing received frames
|
||||||
def worker_received(self):
|
def worker_received(self):
|
||||||
""" """
|
""" """
|
||||||
while True:
|
while True:
|
||||||
|
@ -543,13 +576,13 @@ class RF():
|
||||||
# data[2] = bytes_per_frame
|
# data[2] = bytes_per_frame
|
||||||
data_handler.DATA_QUEUE_RECEIVED.put([data[0], data[1], data[2]])
|
data_handler.DATA_QUEUE_RECEIVED.put([data[0], data[1], data[2]])
|
||||||
self.modem_received_queue.task_done()
|
self.modem_received_queue.task_done()
|
||||||
|
|
||||||
|
|
||||||
def get_frequency_offset(self, freedv):
|
def get_frequency_offset(self, freedv):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
freedv:
|
freedv:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -560,13 +593,13 @@ class RF():
|
||||||
offset = round(modemStats.foff) * (-1)
|
offset = round(modemStats.foff) * (-1)
|
||||||
static.FREQ_OFFSET = offset
|
static.FREQ_OFFSET = offset
|
||||||
return offset
|
return offset
|
||||||
|
|
||||||
|
|
||||||
def get_scatter(self, freedv):
|
def get_scatter(self, freedv):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
freedv:
|
freedv:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -596,12 +629,12 @@ class RF():
|
||||||
scatterdata_small = scatterdata[::10]
|
scatterdata_small = scatterdata[::10]
|
||||||
static.SCATTER = scatterdata_small
|
static.SCATTER = scatterdata_small
|
||||||
|
|
||||||
|
|
||||||
def calculate_snr(self, freedv):
|
def calculate_snr(self, freedv):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
freedv:
|
freedv:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -633,19 +666,19 @@ class RF():
|
||||||
static.HAMLIB_MODE = self.hamlib.get_mode()
|
static.HAMLIB_MODE = self.hamlib.get_mode()
|
||||||
static.HAMLIB_BANDWITH = self.hamlib.get_bandwith()
|
static.HAMLIB_BANDWITH = self.hamlib.get_bandwith()
|
||||||
|
|
||||||
|
|
||||||
def calculate_fft(self):
|
def calculate_fft(self):
|
||||||
""" """
|
""" """
|
||||||
# channel_busy_delay counter
|
# channel_busy_delay counter
|
||||||
channel_busy_delay = 0
|
channel_busy_delay = 0
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
#time.sleep(0.01)
|
#time.sleep(0.01)
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
# WE NEED TO OPTIMIZE THIS!
|
# WE NEED TO OPTIMIZE THIS!
|
||||||
|
|
||||||
if len(self.fft_data) >= 128:
|
if len(self.fft_data) >= 128:
|
||||||
|
|
||||||
# https://gist.github.com/ZWMiller/53232427efc5088007cab6feee7c6e4c
|
# https://gist.github.com/ZWMiller/53232427efc5088007cab6feee7c6e4c
|
||||||
# Fast Fourier Transform, 10*log10(abs) is to scale it to dB
|
# Fast Fourier Transform, 10*log10(abs) is to scale it to dB
|
||||||
# and make sure it's not imaginary
|
# and make sure it's not imaginary
|
||||||
|
@ -656,7 +689,7 @@ class RF():
|
||||||
# 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))
|
||||||
|
|
||||||
# get average of dfft
|
# get average of dfft
|
||||||
avg = np.mean(dfft)
|
avg = np.mean(dfft)
|
||||||
|
|
||||||
|
@ -665,15 +698,15 @@ class RF():
|
||||||
# data higher than the average must be a signal. Therefore we are setting it to 100 so it will be highlighted
|
# data higher than the average must be a signal. Therefore we are setting it to 100 so it will be highlighted
|
||||||
# have to do this when we are not transmittig so our own sending data will not affect this too much
|
# have to do this when we are not transmittig so our own sending data will not affect this too much
|
||||||
if not static.TRANSMITTING:
|
if not static.TRANSMITTING:
|
||||||
dfft[dfft>avg+10] = 100
|
dfft[dfft>avg+10] = 100
|
||||||
|
|
||||||
# calculate audio max value
|
# calculate audio max value
|
||||||
# static.AUDIO_RMS = np.amax(self.fft_data)
|
# static.AUDIO_RMS = np.amax(self.fft_data)
|
||||||
|
|
||||||
|
|
||||||
# check for signals higher than average by checking for "100"
|
# check for signals higher than average by checking for "100"
|
||||||
# if we have a signal, increment our channel_busy delay counter so we have a smoother state toggle
|
# if we have a signal, increment our channel_busy delay counter so we have a smoother state toggle
|
||||||
|
|
||||||
if np.sum(dfft[dfft>avg+10]) >= 300 and not static.TRANSMITTING:
|
if np.sum(dfft[dfft>avg+10]) >= 300 and not static.TRANSMITTING:
|
||||||
static.CHANNEL_BUSY = True
|
static.CHANNEL_BUSY = True
|
||||||
channel_busy_delay += 5
|
channel_busy_delay += 5
|
||||||
|
@ -681,56 +714,56 @@ class RF():
|
||||||
if channel_busy_delay > 50:
|
if channel_busy_delay > 50:
|
||||||
channel_busy_delay = 50
|
channel_busy_delay = 50
|
||||||
else:
|
else:
|
||||||
# decrement channel busy counter if no signal has been detected.
|
# decrement channel busy counter if no signal has been detected.
|
||||||
channel_busy_delay -= 1
|
channel_busy_delay -= 1
|
||||||
if channel_busy_delay < 0:
|
if channel_busy_delay < 0:
|
||||||
channel_busy_delay = 0
|
channel_busy_delay = 0
|
||||||
# if our channel busy counter reached 0, we toggle state to False
|
# if our channel busy counter reached 0, we toggle state to False
|
||||||
if channel_busy_delay == 0:
|
if channel_busy_delay == 0:
|
||||||
static.CHANNEL_BUSY = False
|
static.CHANNEL_BUSY = False
|
||||||
|
|
||||||
# round data to decrease size
|
# round data to decrease size
|
||||||
dfft = np.around(dfft, 0)
|
dfft = np.around(dfft, 0)
|
||||||
dfftlist = dfft.tolist()
|
dfftlist = dfft.tolist()
|
||||||
|
|
||||||
static.FFT = dfftlist[0:320] #320 --> bandwith 3000
|
static.FFT = dfftlist[0:320] #320 --> bandwith 3000
|
||||||
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
|
|
||||||
structlog.get_logger("structlog").debug("[TNC] Setting fft=0")
|
structlog.get_logger("structlog").debug("[TNC] Setting fft=0")
|
||||||
# else 0
|
# else 0
|
||||||
static.FFT = [0]
|
static.FFT = [0]
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_frames_per_burst(self, n_frames_per_burst):
|
def set_frames_per_burst(self, n_frames_per_burst):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
n_frames_per_burst:
|
n_frames_per_burst:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
codec2.api.freedv_set_frames_per_burst(self.datac1_freedv,n_frames_per_burst)
|
codec2.api.freedv_set_frames_per_burst(self.datac1_freedv,n_frames_per_burst)
|
||||||
codec2.api.freedv_set_frames_per_burst(self.datac3_freedv,n_frames_per_burst)
|
codec2.api.freedv_set_frames_per_burst(self.datac3_freedv,n_frames_per_burst)
|
||||||
codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0,n_frames_per_burst)
|
codec2.api.freedv_set_frames_per_burst(self.fsk_ldpc_freedv_0,n_frames_per_burst)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_bytes_per_frame(mode):
|
def get_bytes_per_frame(mode):
|
||||||
"""
|
"""
|
||||||
provide bytes per frame information for accessing from data handler
|
provide bytes per frame information for accessing from data handler
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if mode == 200:
|
if mode == 200:
|
||||||
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), c_void_p)
|
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_0_ADV)), c_void_p)
|
||||||
elif mode == 201:
|
elif mode == 201:
|
||||||
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), c_void_p)
|
freedv = cast(codec2.api.freedv_open_advanced(codec2.api.FREEDV_MODE_FSK_LDPC, ctypes.byref(codec2.api.FREEDV_MODE_FSK_LDPC_1_ADV)), c_void_p)
|
||||||
else:
|
else:
|
||||||
|
@ -738,10 +771,10 @@ def get_bytes_per_frame(mode):
|
||||||
|
|
||||||
# get number of bytes per frame for mode
|
# get number of bytes per frame for mode
|
||||||
return int(codec2.api.freedv_get_bits_per_modem_frame(freedv)/8)
|
return int(codec2.api.freedv_get_bits_per_modem_frame(freedv)/8)
|
||||||
|
|
||||||
|
|
||||||
def set_audio_volume(datalist, volume):
|
def set_audio_volume(datalist, volume):
|
||||||
data = np.fromstring(datalist, np.int16) * (volume / 100.)
|
data = np.fromstring(datalist, np.int16) * (volume / 100.)
|
||||||
return data.astype(np.int16)
|
return data.astype(np.int16)
|
||||||
|
|
||||||
|
|
||||||
|
|
82
tnc/rig.py
82
tnc/rig.py
|
@ -20,17 +20,17 @@ except:
|
||||||
sys.path.append(app_path)
|
sys.path.append(app_path)
|
||||||
|
|
||||||
|
|
||||||
# try importing hamlib
|
# try importing hamlib
|
||||||
try:
|
try:
|
||||||
# get python version
|
# get python version
|
||||||
python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1])
|
python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1])
|
||||||
|
|
||||||
# installation path for Ubuntu 20.04 LTS python modules
|
# installation path for Ubuntu 20.04 LTS python modules
|
||||||
#sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages')
|
#sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages')
|
||||||
|
|
||||||
# installation path for Ubuntu 20.10 +
|
# installation path for Ubuntu 20.10 +
|
||||||
sys.path.append('/usr/local/lib/')
|
sys.path.append('/usr/local/lib/')
|
||||||
|
|
||||||
# installation path for Suse
|
# installation path for Suse
|
||||||
sys.path.append('/usr/local/lib64/python'+ python_version +'/site-packages')
|
sys.path.append('/usr/local/lib64/python'+ python_version +'/site-packages')
|
||||||
|
|
||||||
|
@ -41,14 +41,14 @@ try:
|
||||||
sys.path.append('/usr/local/lib/python3.8/site-packages')
|
sys.path.append('/usr/local/lib/python3.8/site-packages')
|
||||||
sys.path.append('/usr/local/lib/python3.9/site-packages')
|
sys.path.append('/usr/local/lib/python3.9/site-packages')
|
||||||
sys.path.append('/usr/local/lib/python3.10/site-packages')
|
sys.path.append('/usr/local/lib/python3.10/site-packages')
|
||||||
|
|
||||||
sys.path.append('lib/hamlib/linux/python3.8/site-packages')
|
sys.path.append('lib/hamlib/linux/python3.8/site-packages')
|
||||||
import Hamlib
|
import Hamlib
|
||||||
|
|
||||||
# https://stackoverflow.com/a/4703409
|
# https://stackoverflow.com/a/4703409
|
||||||
hamlib_version = re.findall(r"[-+]?\d*\.?\d+|\d+", Hamlib.cvar.hamlib_version)
|
hamlib_version = re.findall(r"[-+]?\d*\.?\d+|\d+", Hamlib.cvar.hamlib_version)
|
||||||
hamlib_version = float(hamlib_version[0])
|
hamlib_version = float(hamlib_version[0])
|
||||||
|
|
||||||
min_hamlib_version = 4.1
|
min_hamlib_version = 4.1
|
||||||
if hamlib_version > min_hamlib_version:
|
if hamlib_version > min_hamlib_version:
|
||||||
structlog.get_logger("structlog").info("[RIG] Hamlib found", version=hamlib_version)
|
structlog.get_logger("structlog").info("[RIG] Hamlib found", version=hamlib_version)
|
||||||
|
@ -68,15 +68,15 @@ except Exception as e:
|
||||||
else:
|
else:
|
||||||
raise Exception
|
raise Exception
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
structlog.get_logger("structlog").critical("[RIG] HAMLIB NOT INSTALLED", error=e)
|
structlog.get_logger("structlog").critical("[RIG] HAMLIB NOT INSTALLED", error=e)
|
||||||
hamlib_version = 0
|
hamlib_version = 0
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
class radio:
|
class radio:
|
||||||
""" """
|
""" """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.devicename = ''
|
self.devicename = ''
|
||||||
self.devicenumber = ''
|
self.devicenumber = ''
|
||||||
self.deviceport = ''
|
self.deviceport = ''
|
||||||
|
@ -87,26 +87,26 @@ class radio:
|
||||||
self.data_bits = ''
|
self.data_bits = ''
|
||||||
self.stop_bits = ''
|
self.stop_bits = ''
|
||||||
self.handshake = ''
|
self.handshake = ''
|
||||||
|
|
||||||
def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_port, rigctld_ip):
|
def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_port, rigctld_ip):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
devicename:
|
devicename:
|
||||||
deviceport:
|
deviceport:
|
||||||
hamlib_ptt_type:
|
hamlib_ptt_type:
|
||||||
serialspeed:
|
serialspeed:
|
||||||
pttport:
|
pttport:
|
||||||
data_bits:
|
data_bits:
|
||||||
stop_bits:
|
stop_bits:
|
||||||
handshake:
|
handshake:
|
||||||
rigctld_port:
|
rigctld_port:
|
||||||
rigctld_ip:
|
rigctld_ip:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.devicename = devicename
|
self.devicename = devicename
|
||||||
self.deviceport = str(deviceport)
|
self.deviceport = str(deviceport)
|
||||||
self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing
|
self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing
|
||||||
|
@ -115,8 +115,8 @@ class radio:
|
||||||
self.data_bits = str(data_bits)
|
self.data_bits = str(data_bits)
|
||||||
self.stop_bits = str(stop_bits)
|
self.stop_bits = str(stop_bits)
|
||||||
self.handshake = str(handshake)
|
self.handshake = str(handshake)
|
||||||
|
|
||||||
|
|
||||||
# try to init hamlib
|
# try to init hamlib
|
||||||
try:
|
try:
|
||||||
Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE)
|
Hamlib.rig_set_debug(Hamlib.RIG_DEBUG_NONE)
|
||||||
|
@ -127,8 +127,8 @@ class radio:
|
||||||
except:
|
except:
|
||||||
structlog.get_logger("structlog").error("[RIG] Hamlib: rig not supported...")
|
structlog.get_logger("structlog").error("[RIG] Hamlib: rig not supported...")
|
||||||
self.devicenumber = 0
|
self.devicenumber = 0
|
||||||
|
|
||||||
|
|
||||||
self.my_rig = Hamlib.Rig(self.devicenumber)
|
self.my_rig = Hamlib.Rig(self.devicenumber)
|
||||||
self.my_rig.set_conf("rig_pathname", self.deviceport)
|
self.my_rig.set_conf("rig_pathname", self.deviceport)
|
||||||
self.my_rig.set_conf("retry", "5")
|
self.my_rig.set_conf("retry", "5")
|
||||||
|
@ -137,10 +137,10 @@ class radio:
|
||||||
self.my_rig.set_conf("stop_bits", self.stop_bits)
|
self.my_rig.set_conf("stop_bits", self.stop_bits)
|
||||||
self.my_rig.set_conf("data_bits", self.data_bits)
|
self.my_rig.set_conf("data_bits", self.data_bits)
|
||||||
self.my_rig.set_conf("ptt_pathname", self.pttport)
|
self.my_rig.set_conf("ptt_pathname", self.pttport)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if self.hamlib_ptt_type == 'RIG':
|
if self.hamlib_ptt_type == 'RIG':
|
||||||
self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG
|
self.hamlib_ptt_type = Hamlib.RIG_PTT_RIG
|
||||||
self.my_rig.set_conf("ptt_type", 'RIG')
|
self.my_rig.set_conf("ptt_type", 'RIG')
|
||||||
|
@ -176,7 +176,7 @@ class radio:
|
||||||
|
|
||||||
elif self.hamlib_ptt_type == 'RIG_PTT_NONE':
|
elif self.hamlib_ptt_type == 'RIG_PTT_NONE':
|
||||||
self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE
|
self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE
|
||||||
|
|
||||||
else: #self.hamlib_ptt_type == 'RIG_PTT_NONE':
|
else: #self.hamlib_ptt_type == 'RIG_PTT_NONE':
|
||||||
self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE
|
self.hamlib_ptt_type = Hamlib.RIG_PTT_NONE
|
||||||
|
|
||||||
|
@ -185,13 +185,13 @@ class radio:
|
||||||
|
|
||||||
self.my_rig.open()
|
self.my_rig.open()
|
||||||
atexit.register(self.my_rig.close)
|
atexit.register(self.my_rig.close)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# lets determine the error message when opening rig
|
# lets determine the error message when opening rig
|
||||||
error = str(Hamlib.rigerror(my_rig.error_status)).splitlines()
|
error = str(Hamlib.rigerror(my_rig.error_status)).splitlines()
|
||||||
error = error[1].split('err=')
|
error = error[1].split('err=')
|
||||||
error = error[1]
|
error = error[1]
|
||||||
|
|
||||||
if error == 'Permission denied':
|
if error == 'Permission denied':
|
||||||
structlog.get_logger("structlog").error("[RIG] Hamlib has no permissions", e = error)
|
structlog.get_logger("structlog").error("[RIG] Hamlib has no permissions", e = error)
|
||||||
help_url = 'https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions'
|
help_url = 'https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions'
|
||||||
|
@ -212,16 +212,16 @@ class radio:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
structlog.get_logger("structlog").error("[RIG] Hamlib - can't open rig", error=e, e=sys.exc_info()[0])
|
structlog.get_logger("structlog").error("[RIG] Hamlib - can't open rig", error=e, e=sys.exc_info()[0])
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_frequency(self):
|
def get_frequency(self):
|
||||||
""" """
|
""" """
|
||||||
return int(self.my_rig.get_freq())
|
return int(self.my_rig.get_freq())
|
||||||
|
|
||||||
def get_mode(self):
|
def get_mode(self):
|
||||||
""" """
|
""" """
|
||||||
(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
||||||
return Hamlib.rig_strrmode(hamlib_mode)
|
return Hamlib.rig_strrmode(hamlib_mode)
|
||||||
|
|
||||||
def get_bandwith(self):
|
def get_bandwith(self):
|
||||||
""" """
|
""" """
|
||||||
(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
||||||
|
@ -230,16 +230,16 @@ class radio:
|
||||||
# not needed yet beacuse of some possible problems
|
# not needed yet beacuse of some possible problems
|
||||||
#def set_mode(self, mode):
|
#def set_mode(self, mode):
|
||||||
# return 0
|
# return 0
|
||||||
|
|
||||||
def get_ptt(self):
|
def get_ptt(self):
|
||||||
""" """
|
""" """
|
||||||
return self.my_rig.get_ptt()
|
return self.my_rig.get_ptt()
|
||||||
|
|
||||||
def set_ptt(self, state):
|
def set_ptt(self, state):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
state:
|
state:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ class radio:
|
||||||
else:
|
else:
|
||||||
self.my_rig.set_ptt(Hamlib.RIG_VFO_CURR, 0)
|
self.my_rig.set_ptt(Hamlib.RIG_VFO_CURR, 0)
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def close_rig(self):
|
def close_rig(self):
|
||||||
""" """
|
""" """
|
||||||
self.my_rig.close()
|
self.my_rig.close()
|
||||||
|
|
|
@ -17,11 +17,11 @@ import os
|
||||||
|
|
||||||
# set global hamlib version
|
# set global hamlib version
|
||||||
hamlib_version = 0
|
hamlib_version = 0
|
||||||
|
|
||||||
class radio:
|
class radio:
|
||||||
""" """
|
""" """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.devicename = ''
|
self.devicename = ''
|
||||||
self.devicenumber = ''
|
self.devicenumber = ''
|
||||||
self.deviceport = ''
|
self.deviceport = ''
|
||||||
|
@ -32,26 +32,26 @@ class radio:
|
||||||
self.data_bits = ''
|
self.data_bits = ''
|
||||||
self.stop_bits = ''
|
self.stop_bits = ''
|
||||||
self.handshake = ''
|
self.handshake = ''
|
||||||
|
|
||||||
def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port):
|
def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
devicename:
|
devicename:
|
||||||
deviceport:
|
deviceport:
|
||||||
hamlib_ptt_type:
|
hamlib_ptt_type:
|
||||||
serialspeed:
|
serialspeed:
|
||||||
pttport:
|
pttport:
|
||||||
data_bits:
|
data_bits:
|
||||||
stop_bits:
|
stop_bits:
|
||||||
handshake:
|
handshake:
|
||||||
rigctld_ip:
|
rigctld_ip:
|
||||||
rigctld_port:
|
rigctld_port:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.devicename = devicename
|
self.devicename = devicename
|
||||||
self.deviceport = deviceport
|
self.deviceport = deviceport
|
||||||
self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing
|
self.serialspeed = str(serialspeed) # we need to ensure this is a str, otherwise set_conf functions are crashing
|
||||||
|
@ -60,15 +60,15 @@ class radio:
|
||||||
self.data_bits = data_bits
|
self.data_bits = data_bits
|
||||||
self.stop_bits = stop_bits
|
self.stop_bits = stop_bits
|
||||||
self.handshake = handshake
|
self.handshake = handshake
|
||||||
|
|
||||||
|
|
||||||
# check if we are running in a pyinstaller environment
|
# check if we are running in a pyinstaller environment
|
||||||
try:
|
try:
|
||||||
app_path = sys._MEIPASS
|
app_path = sys._MEIPASS
|
||||||
except:
|
except:
|
||||||
app_path = os.path.abspath(".")
|
app_path = os.path.abspath(".")
|
||||||
sys.path.append(app_path)
|
sys.path.append(app_path)
|
||||||
|
|
||||||
# get devicenumber by looking for deviceobject in Hamlib module
|
# get devicenumber by looking for deviceobject in Hamlib module
|
||||||
try:
|
try:
|
||||||
import Hamlib
|
import Hamlib
|
||||||
|
@ -78,12 +78,12 @@ class radio:
|
||||||
self.devicenumber = int(self.devicename)
|
self.devicenumber = int(self.devicename)
|
||||||
else:
|
else:
|
||||||
self.devicenumber = 6 #dummy
|
self.devicenumber = 6 #dummy
|
||||||
structlog.get_logger("structlog").warning("[RIGCTL] RADIO NOT FOUND USING DUMMY!", error=e)
|
structlog.get_logger("structlog").warning("[RIGCTL] RADIO NOT FOUND USING DUMMY!", error=e)
|
||||||
|
|
||||||
# set deviceport to dummy port, if we selected dummy model
|
# set deviceport to dummy port, if we selected dummy model
|
||||||
if self.devicenumber == 1 or self.devicenumber == 6:
|
if self.devicenumber == 1 or self.devicenumber == 6:
|
||||||
self.deviceport = '/dev/ttyUSB0'
|
self.deviceport = '/dev/ttyUSB0'
|
||||||
|
|
||||||
print(self.devicenumber, self.deviceport, self.serialspeed)
|
print(self.devicenumber, self.deviceport, self.serialspeed)
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,17 +93,17 @@ class radio:
|
||||||
# this is really a hack...somewhen we need a native hamlib integration for windows
|
# this is really a hack...somewhen we need a native hamlib integration for windows
|
||||||
if sys.platform == 'win32' or sys.platform == 'win64':
|
if sys.platform == 'win32' or sys.platform == 'win64':
|
||||||
self.cmd = app_path + 'lib\\hamlib\\'+sys.platform+'\\rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed))
|
self.cmd = app_path + 'lib\\hamlib\\'+sys.platform+'\\rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.cmd = 'rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed))
|
self.cmd = 'rigctl -m %d -r %s -s %d ' % (int(self.devicenumber), self.deviceport, int(self.serialspeed))
|
||||||
|
|
||||||
# eseguo semplicemente rigctl con il solo comando T 1 o T 0 per
|
# eseguo semplicemente rigctl con il solo comando T 1 o T 0 per
|
||||||
# il set e t per il get
|
# il set e t per il get
|
||||||
|
|
||||||
# set ptt to false if ptt is stuck for some reason
|
# set ptt to false if ptt is stuck for some reason
|
||||||
self.set_ptt(False)
|
self.set_ptt(False)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_frequency(self):
|
def get_frequency(self):
|
||||||
""" """
|
""" """
|
||||||
cmd = self.cmd + ' f'
|
cmd = self.cmd + ' f'
|
||||||
|
@ -116,7 +116,7 @@ class radio:
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_mode(self):
|
def get_mode(self):
|
||||||
""" """
|
""" """
|
||||||
#(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
#(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
||||||
|
@ -126,7 +126,7 @@ class radio:
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_bandwith(self):
|
def get_bandwith(self):
|
||||||
""" """
|
""" """
|
||||||
#(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
#(hamlib_mode, bandwith) = self.my_rig.get_mode()
|
||||||
|
@ -141,18 +141,18 @@ class radio:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# non usata
|
# non usata
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def get_ptt(self):
|
def get_ptt(self):
|
||||||
""" """
|
""" """
|
||||||
cmd = self.cmd + ' t'
|
cmd = self.cmd + ' t'
|
||||||
sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
|
sw_proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
status = sw_proc.communicate()[0]
|
status = sw_proc.communicate()[0]
|
||||||
|
|
||||||
|
@ -160,12 +160,12 @@ class radio:
|
||||||
return status
|
return status
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_ptt(self, state):
|
def set_ptt(self, state):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
state:
|
state:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -178,12 +178,12 @@ class radio:
|
||||||
cmd = cmd + '0'
|
cmd = cmd + '0'
|
||||||
print('set_ptt', cmd)
|
print('set_ptt', cmd)
|
||||||
|
|
||||||
sw_proc = subprocess.Popen(cmd, shell=True, text=True)
|
sw_proc = subprocess.Popen(cmd, shell=True, text=True)
|
||||||
try:
|
try:
|
||||||
return state
|
return state
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def close_rig(self):
|
def close_rig(self):
|
||||||
""" """
|
""" """
|
||||||
#self.my_rig.close()
|
#self.my_rig.close()
|
||||||
|
|
|
@ -15,7 +15,7 @@ hamlib_version = 0
|
||||||
|
|
||||||
class radio():
|
class radio():
|
||||||
"""rotctld (hamlib) communication class"""
|
"""rotctld (hamlib) communication class"""
|
||||||
# Note: This is a massive hack.
|
# Note: This is a massive hack.
|
||||||
|
|
||||||
def __init__(self, hostname="localhost", port=4532, poll_rate=5, timeout=5):
|
def __init__(self, hostname="localhost", port=4532, poll_rate=5, timeout=5):
|
||||||
""" Open a connection to rotctld, and test it for validity """
|
""" Open a connection to rotctld, and test it for validity """
|
||||||
|
@ -31,31 +31,31 @@ class radio():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
devicename:
|
devicename:
|
||||||
deviceport:
|
deviceport:
|
||||||
hamlib_ptt_type:
|
hamlib_ptt_type:
|
||||||
serialspeed:
|
serialspeed:
|
||||||
pttport:
|
pttport:
|
||||||
data_bits:
|
data_bits:
|
||||||
stop_bits:
|
stop_bits:
|
||||||
handshake:
|
handshake:
|
||||||
rigctld_ip:
|
rigctld_ip:
|
||||||
rigctld_port:
|
rigctld_port:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.hostname = rigctld_ip
|
self.hostname = rigctld_ip
|
||||||
self.port = int(rigctld_port)
|
self.port = int(rigctld_port)
|
||||||
|
|
||||||
|
|
||||||
if self.connect():
|
if self.connect():
|
||||||
logging.debug(f"Rigctl intialized")
|
logging.debug(f"Rigctl intialized")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
structlog.get_logger("structlog").error("[RIGCTLD] Can't connect to rigctld!", ip=self.hostname, port=self.port)
|
structlog.get_logger("structlog").error("[RIGCTLD] Can't connect to rigctld!", ip=self.hostname, port=self.port)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
"""Connect to rigctld instance"""
|
"""Connect to rigctld instance"""
|
||||||
if not self.connected:
|
if not self.connected:
|
||||||
|
@ -69,7 +69,7 @@ class radio():
|
||||||
self.close_rig()
|
self.close_rig()
|
||||||
structlog.get_logger("structlog").warning("[RIGCTLD] Connection to rigctld refused! Reconnect...", ip=self.hostname, port=self.port, e=e)
|
structlog.get_logger("structlog").warning("[RIGCTLD] Connection to rigctld refused! Reconnect...", ip=self.hostname, port=self.port, e=e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def close_rig(self):
|
def close_rig(self):
|
||||||
""" """
|
""" """
|
||||||
self.sock.close()
|
self.sock.close()
|
||||||
|
@ -81,7 +81,7 @@ class radio():
|
||||||
and return the return value.
|
and return the return value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
command:
|
command:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class radio():
|
||||||
structlog.get_logger("structlog").warning("[RIGCTLD] No command response!", command=command, ip=self.hostname, port=self.port)
|
structlog.get_logger("structlog").warning("[RIGCTLD] No command response!", command=command, ip=self.hostname, port=self.port)
|
||||||
self.connected = False
|
self.connected = False
|
||||||
else:
|
else:
|
||||||
|
|
||||||
# reconnecting....
|
# reconnecting....
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
self.connect()
|
self.connect()
|
||||||
|
@ -111,7 +111,7 @@ class radio():
|
||||||
data = self.send_command(b"m")
|
data = self.send_command(b"m")
|
||||||
data = data.split(b'\n')
|
data = data.split(b'\n')
|
||||||
mode = data[0]
|
mode = data[0]
|
||||||
return mode.decode("utf-8")
|
return mode.decode("utf-8")
|
||||||
except:
|
except:
|
||||||
0
|
0
|
||||||
def get_bandwith(self):
|
def get_bandwith(self):
|
||||||
|
@ -123,7 +123,7 @@ class radio():
|
||||||
return bandwith.decode("utf-8")
|
return bandwith.decode("utf-8")
|
||||||
except:
|
except:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def get_frequency(self):
|
def get_frequency(self):
|
||||||
""" """
|
""" """
|
||||||
try:
|
try:
|
||||||
|
@ -131,19 +131,19 @@ class radio():
|
||||||
return frequency.decode("utf-8")
|
return frequency.decode("utf-8")
|
||||||
except:
|
except:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def get_ptt(self):
|
def get_ptt(self):
|
||||||
""" """
|
""" """
|
||||||
try:
|
try:
|
||||||
return self.send_command(b"t")
|
return self.send_command(b"t")
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_ptt(self, state):
|
def set_ptt(self, state):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
state:
|
state:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -153,6 +153,6 @@ class radio():
|
||||||
self.send_command(b"T 1")
|
self.send_command(b"T 1")
|
||||||
else:
|
else:
|
||||||
self.send_command(b"T 0")
|
self.send_command(b"T 0")
|
||||||
return state
|
return state
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -3,32 +3,32 @@
|
||||||
import structlog
|
import structlog
|
||||||
|
|
||||||
hamlib_version = 0
|
hamlib_version = 0
|
||||||
|
|
||||||
class radio:
|
class radio:
|
||||||
""" """
|
""" """
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def open_rig(self, **kwargs):
|
def open_rig(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
**kwargs:
|
**kwargs:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_frequency(self):
|
def get_frequency(self):
|
||||||
""" """
|
""" """
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_mode(self):
|
def get_mode(self):
|
||||||
""" """
|
""" """
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_bandwith(self):
|
def get_bandwith(self):
|
||||||
""" """
|
""" """
|
||||||
return None
|
return None
|
||||||
|
@ -37,28 +37,28 @@ class radio:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode:
|
mode:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_ptt(self):
|
def get_ptt(self):
|
||||||
""" """
|
""" """
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_ptt(self, state):
|
def set_ptt(self, state):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
state:
|
state:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def close_rig(self):
|
def close_rig(self):
|
||||||
""" """
|
""" """
|
||||||
return
|
return
|
||||||
|
|
198
tnc/sock.py
198
tnc/sock.py
|
@ -7,11 +7,11 @@ Created on Fri Dec 25 21:25:14 2020
|
||||||
|
|
||||||
# GET COMMANDS
|
# GET COMMANDS
|
||||||
# "command" : "..."
|
# "command" : "..."
|
||||||
|
|
||||||
# SET COMMANDS
|
# SET COMMANDS
|
||||||
# "command" : "..."
|
# "command" : "..."
|
||||||
# "parameter" : " ..."
|
# "parameter" : " ..."
|
||||||
|
|
||||||
# DATA COMMANDS
|
# DATA COMMANDS
|
||||||
# "command" : "..."
|
# "command" : "..."
|
||||||
# "type" : "..."
|
# "type" : "..."
|
||||||
|
@ -51,25 +51,25 @@ class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
the socket handler base class
|
the socket handler base class
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
""" """
|
""" """
|
||||||
|
|
||||||
|
|
||||||
def send_to_client(self):
|
def send_to_client(self):
|
||||||
"""
|
"""
|
||||||
function called by socket handler
|
function called by socket handler
|
||||||
send data to a network client if available
|
send data to a network client if available
|
||||||
|
|
||||||
"""
|
"""
|
||||||
tempdata = b''
|
tempdata = b''
|
||||||
while self.connection_alive and not CLOSE_SIGNAL:
|
while self.connection_alive and not CLOSE_SIGNAL:
|
||||||
|
|
||||||
# send tnc state as network stream
|
# send tnc state as network stream
|
||||||
# check server port against daemon port and send corresponding data
|
# check server port against daemon port and send corresponding data
|
||||||
|
|
||||||
if self.server.server_address[1] == static.PORT and not static.TNCSTARTED:
|
if self.server.server_address[1] == static.PORT and not static.TNCSTARTED:
|
||||||
data = send_tnc_state()
|
data = send_tnc_state()
|
||||||
if data != tempdata:
|
if data != tempdata:
|
||||||
|
@ -81,13 +81,13 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
tempdata = data
|
tempdata = data
|
||||||
SOCKET_QUEUE.put(data)
|
SOCKET_QUEUE.put(data)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
while not SOCKET_QUEUE.empty():
|
while not SOCKET_QUEUE.empty():
|
||||||
data = SOCKET_QUEUE.get()
|
data = SOCKET_QUEUE.get()
|
||||||
sock_data = bytes(data, 'utf-8')
|
sock_data = bytes(data, 'utf-8')
|
||||||
sock_data += b'\n' # append line limiter
|
sock_data += b'\n' # append line limiter
|
||||||
|
|
||||||
# send data to all clients
|
# send data to all clients
|
||||||
#try:
|
#try:
|
||||||
for client in CONNECTED_CLIENTS:
|
for client in CONNECTED_CLIENTS:
|
||||||
|
@ -101,7 +101,7 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
# we want to transmit scatter data only once to reduce network traffic
|
# we want to transmit scatter data only once to reduce network traffic
|
||||||
static.SCATTER = []
|
static.SCATTER = []
|
||||||
# we want to display INFO messages only once
|
# we want to display INFO messages only once
|
||||||
static.INFO = []
|
static.INFO = []
|
||||||
#self.request.sendall(sock_data)
|
#self.request.sendall(sock_data)
|
||||||
time.sleep(0.15)
|
time.sleep(0.15)
|
||||||
|
|
||||||
|
@ -115,18 +115,18 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
try:
|
try:
|
||||||
chunk = self.request.recv(1024)
|
chunk = self.request.recv(1024)
|
||||||
data += chunk
|
data += chunk
|
||||||
|
|
||||||
if chunk == b'':
|
if chunk == b'':
|
||||||
#print("connection broken. Closing...")
|
#print("connection broken. Closing...")
|
||||||
self.connection_alive = False
|
self.connection_alive = False
|
||||||
|
|
||||||
|
|
||||||
if data.startswith(b'{') and data.endswith(b'}\n'):
|
|
||||||
|
if data.startswith(b'{') and data.endswith(b'}\n'):
|
||||||
# split data by \n if we have multiple commands in socket buffer
|
# split data by \n if we have multiple commands in socket buffer
|
||||||
data = data.split(b'\n')
|
data = data.split(b'\n')
|
||||||
# remove empty data
|
# remove empty data
|
||||||
data.remove(b'')
|
data.remove(b'')
|
||||||
|
|
||||||
# iterate thorugh data list
|
# iterate thorugh data list
|
||||||
for commands in data:
|
for commands in data:
|
||||||
if self.server.server_address[1] == static.PORT:
|
if self.server.server_address[1] == static.PORT:
|
||||||
|
@ -136,19 +136,19 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
|
|
||||||
# wait some time between processing multiple commands
|
# wait some time between processing multiple commands
|
||||||
# this is only a first test to avoid doubled transmission
|
# this is only a first test to avoid doubled transmission
|
||||||
# we might improve this by only processing one command or
|
# we might improve this by only processing one command or
|
||||||
# doing some kind of selection to determin which commands need to be dropped
|
# doing some kind of selection to determin which commands need to be dropped
|
||||||
# and which one can be processed during a running transmission
|
# and which one can be processed during a running transmission
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
|
|
||||||
# finally delete our rx buffer to be ready for new commands
|
# finally delete our rx buffer to be ready for new commands
|
||||||
data = bytes()
|
data = bytes()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], port=self.client_address[1], e=e)
|
structlog.get_logger("structlog").info("[SCK] Connection closed", ip=self.client_address[0], port=self.client_address[1], e=e)
|
||||||
self.connection_alive = False
|
self.connection_alive = False
|
||||||
|
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
"""
|
"""
|
||||||
socket handler
|
socket handler
|
||||||
|
@ -158,19 +158,19 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
|
|
||||||
structlog.get_logger("structlog").debug("[SCK] Client connected", ip=self.client_address[0], port=self.client_address[1])
|
structlog.get_logger("structlog").debug("[SCK] Client connected", ip=self.client_address[0], port=self.client_address[1])
|
||||||
self.connection_alive = True
|
self.connection_alive = True
|
||||||
|
|
||||||
self.sendThread = threading.Thread(target=self.send_to_client, args=[],daemon=True).start()
|
self.sendThread = threading.Thread(target=self.send_to_client, args=[],daemon=True).start()
|
||||||
self.receiveThread = threading.Thread(target=self.receive_from_client, args=[],daemon=True).start()
|
self.receiveThread = threading.Thread(target=self.receive_from_client, args=[],daemon=True).start()
|
||||||
|
|
||||||
# keep connection alive until we close it
|
# keep connection alive until we close it
|
||||||
while self.connection_alive and not CLOSE_SIGNAL:
|
while self.connection_alive and not CLOSE_SIGNAL:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
""" """
|
""" """
|
||||||
structlog.get_logger("structlog").warning("[SCK] Closing client socket", ip=self.client_address[0], port=self.client_address[1])
|
structlog.get_logger("structlog").warning("[SCK] Closing client socket", ip=self.client_address[0], port=self.client_address[1])
|
||||||
try:
|
try:
|
||||||
CONNECTED_CLIENTS.remove(self.request)
|
CONNECTED_CLIENTS.remove(self.request)
|
||||||
except:
|
except:
|
||||||
|
@ -182,7 +182,7 @@ def process_tnc_commands(data):
|
||||||
process tnc commands
|
process tnc commands
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -198,9 +198,9 @@ def process_tnc_commands(data):
|
||||||
try:
|
try:
|
||||||
static.TX_AUDIO_LEVEL = int(received_json["value"])
|
static.TX_AUDIO_LEVEL = int(received_json["value"])
|
||||||
command_response("tx_audio_level", True)
|
command_response("tx_audio_level", True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("tx_audio_level", False)
|
command_response("tx_audio_level", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,8 +209,8 @@ def process_tnc_commands(data):
|
||||||
try:
|
try:
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['SEND_TEST_FRAME'])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['SEND_TEST_FRAME'])
|
||||||
command_response("send_test_frame", True)
|
command_response("send_test_frame", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("send_test_frame", False)
|
command_response("send_test_frame", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# CQ CQ CQ -----------------------------------------------------
|
# CQ CQ CQ -----------------------------------------------------
|
||||||
|
@ -218,9 +218,9 @@ def process_tnc_commands(data):
|
||||||
try:
|
try:
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['CQ'])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['CQ'])
|
||||||
command_response("cqcqcq", True)
|
command_response("cqcqcq", True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("cqcqcq", False)
|
command_response("cqcqcq", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
# START_BEACON -----------------------------------------------------
|
# START_BEACON -----------------------------------------------------
|
||||||
if received_json["command"] == "start_beacon":
|
if received_json["command"] == "start_beacon":
|
||||||
|
@ -229,21 +229,21 @@ def process_tnc_commands(data):
|
||||||
interval = int(received_json["parameter"])
|
interval = int(received_json["parameter"])
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', interval, True])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', interval, True])
|
||||||
command_response("start_beacon", True)
|
command_response("start_beacon", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("start_beacon", False)
|
command_response("start_beacon", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# STOP_BEACON -----------------------------------------------------
|
# STOP_BEACON -----------------------------------------------------
|
||||||
if received_json["command"] == "stop_beacon":
|
if received_json["command"] == "stop_beacon":
|
||||||
try:
|
try:
|
||||||
structlog.get_logger("structlog").warning("[TNC] Stopping beacon!")
|
structlog.get_logger("structlog").warning("[TNC] Stopping beacon!")
|
||||||
static.BEACON_STATE = False
|
static.BEACON_STATE = False
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', None, False])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['BEACON', None, False])
|
||||||
command_response("stop_beacon", True)
|
command_response("stop_beacon", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("stop_beacon", False)
|
command_response("stop_beacon", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -255,14 +255,14 @@ def process_tnc_commands(data):
|
||||||
# then we are forcing a station ssid = 0
|
# then we are forcing a station ssid = 0
|
||||||
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
||||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||||
|
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['PING', dxcallsign])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['PING', dxcallsign])
|
||||||
command_response("ping", True)
|
command_response("ping", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("ping", False)
|
command_response("ping", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
# CONNECT ----------------------------------------------------------
|
# CONNECT ----------------------------------------------------------
|
||||||
if received_json["type"] == 'arq' and received_json["command"] == "connect":
|
if received_json["type"] == 'arq' and received_json["command"] == "connect":
|
||||||
static.BEACON_PAUSE = True
|
static.BEACON_PAUSE = True
|
||||||
|
@ -275,14 +275,14 @@ def process_tnc_commands(data):
|
||||||
# then we are forcing a station ssid = 0
|
# then we are forcing a station ssid = 0
|
||||||
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
dxcallsign = helpers.callsign_to_bytes(dxcallsign)
|
||||||
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
dxcallsign = helpers.bytes_to_callsign(dxcallsign)
|
||||||
|
|
||||||
static.DXCALLSIGN = dxcallsign
|
static.DXCALLSIGN = dxcallsign
|
||||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||||
|
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['CONNECT', dxcallsign])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['CONNECT', dxcallsign])
|
||||||
command_response("connect", True)
|
command_response("connect", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("connect", False)
|
command_response("connect", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# DISCONNECT ----------------------------------------------------------
|
# DISCONNECT ----------------------------------------------------------
|
||||||
|
@ -291,15 +291,15 @@ def process_tnc_commands(data):
|
||||||
try:
|
try:
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['DISCONNECT'])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['DISCONNECT'])
|
||||||
command_response("disconnect", True)
|
command_response("disconnect", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("disconnect", False)
|
command_response("disconnect", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# TRANSMIT RAW DATA -------------------------------------------
|
# TRANSMIT RAW DATA -------------------------------------------
|
||||||
if received_json["type"] == 'arq' and received_json["command"] == "send_raw":
|
if received_json["type"] == 'arq' and received_json["command"] == "send_raw":
|
||||||
|
|
||||||
static.BEACON_PAUSE = True
|
static.BEACON_PAUSE = True
|
||||||
try:
|
try:
|
||||||
if not static.ARQ_SESSION:
|
if not static.ARQ_SESSION:
|
||||||
dxcallsign = received_json["parameter"][0]["dxcallsign"]
|
dxcallsign = received_json["parameter"][0]["dxcallsign"]
|
||||||
# additional step for beeing sure our callsign is correctly
|
# additional step for beeing sure our callsign is correctly
|
||||||
|
@ -314,37 +314,37 @@ def process_tnc_commands(data):
|
||||||
dxcallsign = static.DXCALLSIGN
|
dxcallsign = static.DXCALLSIGN
|
||||||
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
static.DXCALLSIGN_CRC = helpers.get_crc_24(static.DXCALLSIGN)
|
||||||
|
|
||||||
|
|
||||||
mode = int(received_json["parameter"][0]["mode"])
|
mode = int(received_json["parameter"][0]["mode"])
|
||||||
n_frames = int(received_json["parameter"][0]["n_frames"])
|
n_frames = int(received_json["parameter"][0]["n_frames"])
|
||||||
base64data = received_json["parameter"][0]["data"]
|
base64data = received_json["parameter"][0]["data"]
|
||||||
|
|
||||||
# check if specific callsign is set with different SSID than the TNC is initialized
|
# check if specific callsign is set with different SSID than the TNC is initialized
|
||||||
try:
|
try:
|
||||||
mycallsign = received_json["parameter"][0]["mycallsign"]
|
mycallsign = received_json["parameter"][0]["mycallsign"]
|
||||||
except:
|
except:
|
||||||
mycallsign = static.MYCALLSIGN
|
mycallsign = static.MYCALLSIGN
|
||||||
|
|
||||||
# check if transmission uuid provided else set no-uuid
|
# check if transmission uuid provided else set no-uuid
|
||||||
try:
|
try:
|
||||||
arq_uuid = received_json["uuid"]
|
arq_uuid = received_json["uuid"]
|
||||||
except:
|
except:
|
||||||
arq_uuid = 'no-uuid'
|
arq_uuid = 'no-uuid'
|
||||||
|
|
||||||
if not len(base64data) % 4:
|
if not len(base64data) % 4:
|
||||||
binarydata = base64.b64decode(base64data)
|
binarydata = base64.b64decode(base64data)
|
||||||
|
|
||||||
data_handler.DATA_QUEUE_TRANSMIT.put(['ARQ_RAW', binarydata, mode, n_frames, arq_uuid, mycallsign])
|
data_handler.DATA_QUEUE_TRANSMIT.put(['ARQ_RAW', binarydata, mode, n_frames, arq_uuid, mycallsign])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise TypeError
|
raise TypeError
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("send_raw", False)
|
command_response("send_raw", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# STOP TRANSMISSION ----------------------------------------------------------
|
|
||||||
|
# STOP TRANSMISSION ----------------------------------------------------------
|
||||||
if received_json["type"] == 'arq' and received_json["command"] == "stop_transmission":
|
if received_json["type"] == 'arq' and received_json["command"] == "stop_transmission":
|
||||||
try:
|
try:
|
||||||
if static.TNC_STATE == 'BUSY' or static.ARQ_STATE:
|
if static.TNC_STATE == 'BUSY' or static.ARQ_STATE:
|
||||||
|
@ -353,10 +353,10 @@ def process_tnc_commands(data):
|
||||||
static.TNC_STATE = 'IDLE'
|
static.TNC_STATE = 'IDLE'
|
||||||
static.ARQ_STATE = False
|
static.ARQ_STATE = False
|
||||||
command_response("stop_transmission", True)
|
command_response("stop_transmission", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("stop_transmission", False)
|
command_response("stop_transmission", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
if received_json["type"] == 'get' and received_json["command"] == 'rx_buffer':
|
if received_json["type"] == 'get' and received_json["command"] == 'rx_buffer':
|
||||||
try:
|
try:
|
||||||
|
@ -364,7 +364,7 @@ def process_tnc_commands(data):
|
||||||
"command": "rx_buffer",
|
"command": "rx_buffer",
|
||||||
"data-array": [],
|
"data-array": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in range(0, len(static.RX_BUFFER)):
|
for i in range(0, len(static.RX_BUFFER)):
|
||||||
#print(static.RX_BUFFER[i][4])
|
#print(static.RX_BUFFER[i][4])
|
||||||
#rawdata = json.loads(static.RX_BUFFER[i][4])
|
#rawdata = json.loads(static.RX_BUFFER[i][4])
|
||||||
|
@ -375,18 +375,18 @@ def process_tnc_commands(data):
|
||||||
#self.request.sendall(bytes(jsondata, encoding))
|
#self.request.sendall(bytes(jsondata, encoding))
|
||||||
SOCKET_QUEUE.put(jsondata)
|
SOCKET_QUEUE.put(jsondata)
|
||||||
command_response("rx_buffer", True)
|
command_response("rx_buffer", True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("rx_buffer", False)
|
command_response("rx_buffer", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
if received_json["type"] == 'set' and received_json["command"] == 'del_rx_buffer':
|
if received_json["type"] == 'set' and received_json["command"] == 'del_rx_buffer':
|
||||||
try:
|
try:
|
||||||
static.RX_BUFFER = []
|
static.RX_BUFFER = []
|
||||||
command_response("del_rx_buffer", True)
|
command_response("del_rx_buffer", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("del_rx_buffer", False)
|
command_response("del_rx_buffer", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
# exception, if JSON cant be decoded
|
# exception, if JSON cant be decoded
|
||||||
|
@ -397,7 +397,7 @@ def send_tnc_state():
|
||||||
"""
|
"""
|
||||||
send the tnc state to network
|
send the tnc state to network
|
||||||
"""
|
"""
|
||||||
|
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
|
|
||||||
output = {
|
output = {
|
||||||
|
@ -410,7 +410,7 @@ def send_tnc_state():
|
||||||
"audio_rms": str(static.AUDIO_RMS),
|
"audio_rms": str(static.AUDIO_RMS),
|
||||||
"snr": str(static.SNR),
|
"snr": str(static.SNR),
|
||||||
"frequency": str(static.HAMLIB_FREQUENCY),
|
"frequency": str(static.HAMLIB_FREQUENCY),
|
||||||
"speed_level": str(static.ARQ_SPEED_LEVEL),
|
"speed_level": str(static.ARQ_SPEED_LEVEL),
|
||||||
"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),
|
||||||
|
@ -434,7 +434,7 @@ def send_tnc_state():
|
||||||
# add heard stations to heard stations object
|
# add heard stations to heard stations object
|
||||||
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], "offset": static.HEARD_STATIONS[i][5], "frequency": static.HEARD_STATIONS[i][6]})
|
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], "offset": static.HEARD_STATIONS[i][5], "frequency": static.HEARD_STATIONS[i][6]})
|
||||||
|
|
||||||
jsondata = json.dumps(output)
|
jsondata = json.dumps(output)
|
||||||
return jsondata
|
return jsondata
|
||||||
|
|
||||||
|
@ -444,7 +444,7 @@ def process_daemon_commands(data):
|
||||||
process daemon commands
|
process daemon commands
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data:
|
data:
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
|
@ -465,11 +465,11 @@ def process_daemon_commands(data):
|
||||||
|
|
||||||
command_response("mycallsign", True)
|
command_response("mycallsign", True)
|
||||||
structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC)
|
structlog.get_logger("structlog").info("[DMN] SET MYCALL", call=static.MYCALLSIGN, crc=static.MYCALLSIGN_CRC)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("mycallsign", False)
|
command_response("mycallsign", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
if received_json["type"] == 'set' and received_json["command"] == 'mygrid':
|
if received_json["type"] == 'set' and received_json["command"] == 'mygrid':
|
||||||
try:
|
try:
|
||||||
mygrid = received_json["parameter"]
|
mygrid = received_json["parameter"]
|
||||||
|
@ -480,13 +480,13 @@ def process_daemon_commands(data):
|
||||||
static.MYGRID = bytes(mygrid, 'utf-8')
|
static.MYGRID = bytes(mygrid, 'utf-8')
|
||||||
structlog.get_logger("structlog").info("[SCK] SET MYGRID", grid=static.MYGRID)
|
structlog.get_logger("structlog").info("[SCK] SET MYGRID", grid=static.MYGRID)
|
||||||
command_response("mygrid", True)
|
command_response("mygrid", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("mygrid", False)
|
command_response("mygrid", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
|
|
||||||
if received_json["type"] == 'set' and received_json["command"] == 'start_tnc' and not static.TNCSTARTED:
|
if received_json["type"] == 'set' and received_json["command"] == 'start_tnc' and not static.TNCSTARTED:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mycall = str(received_json["parameter"][0]["mycall"])
|
mycall = str(received_json["parameter"][0]["mycall"])
|
||||||
mygrid = str(received_json["parameter"][0]["mygrid"])
|
mygrid = str(received_json["parameter"][0]["mygrid"])
|
||||||
|
@ -543,9 +543,9 @@ def process_daemon_commands(data):
|
||||||
respond_to_cq \
|
respond_to_cq \
|
||||||
])
|
])
|
||||||
command_response("start_tnc", True)
|
command_response("start_tnc", True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("start_tnc", False)
|
command_response("start_tnc", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
if received_json["type"] == 'get' and received_json["command"] == 'test_hamlib':
|
if received_json["type"] == 'get' and received_json["command"] == 'test_hamlib':
|
||||||
|
@ -577,23 +577,23 @@ def process_daemon_commands(data):
|
||||||
rigctld_port \
|
rigctld_port \
|
||||||
])
|
])
|
||||||
command_response("test_hamlib", True)
|
command_response("test_hamlib", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("test_hamlib", False)
|
command_response("test_hamlib", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
if received_json["type"] == 'set' and received_json["command"] == 'stop_tnc':
|
if received_json["type"] == 'set' and received_json["command"] == 'stop_tnc':
|
||||||
try:
|
try:
|
||||||
static.TNCPROCESS.kill()
|
static.TNCPROCESS.kill()
|
||||||
# unregister process from atexit to avoid process zombies
|
# unregister process from atexit to avoid process zombies
|
||||||
atexit.unregister(static.TNCPROCESS.kill)
|
atexit.unregister(static.TNCPROCESS.kill)
|
||||||
|
|
||||||
structlog.get_logger("structlog").warning("[DMN] Stopping TNC")
|
structlog.get_logger("structlog").warning("[DMN] Stopping TNC")
|
||||||
static.TNCSTARTED = False
|
static.TNCSTARTED = False
|
||||||
command_response("stop_tnc", True)
|
command_response("stop_tnc", True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
command_response("stop_tnc", False)
|
command_response("stop_tnc", False)
|
||||||
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
structlog.get_logger("structlog").warning("[SCK] command execution error", e=e, command=received_json)
|
||||||
|
|
||||||
def send_daemon_state():
|
def send_daemon_state():
|
||||||
"""
|
"""
|
||||||
send the daemon state to network
|
send the daemon state to network
|
||||||
|
@ -613,26 +613,26 @@ def send_daemon_state():
|
||||||
#'ram': str(psutil.virtual_memory().percent),
|
#'ram': str(psutil.virtual_memory().percent),
|
||||||
'version': '0.1'
|
'version': '0.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
if static.TNCSTARTED:
|
if static.TNCSTARTED:
|
||||||
output["daemon_state"].append({"status": "running"})
|
output["daemon_state"].append({"status": "running"})
|
||||||
else:
|
else:
|
||||||
output["daemon_state"].append({"status": "stopped"})
|
output["daemon_state"].append({"status": "stopped"})
|
||||||
|
|
||||||
|
|
||||||
jsondata = json.dumps(output)
|
jsondata = json.dumps(output)
|
||||||
|
|
||||||
return jsondata
|
return jsondata
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
structlog.get_logger("structlog").warning("[SCK] error", e=e)
|
structlog.get_logger("structlog").warning("[SCK] error", e=e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def command_response(command, status):
|
def command_response(command, status):
|
||||||
if status:
|
if status:
|
||||||
status = "OK"
|
status = "OK"
|
||||||
else:
|
else:
|
||||||
status = "Failed"
|
status = "Failed"
|
||||||
|
|
||||||
jsondata = {"command_response": command, "status" : status}
|
jsondata = {"command_response": command, "status" : status}
|
||||||
data_out = json.dumps(jsondata)
|
data_out = json.dumps(jsondata)
|
||||||
SOCKET_QUEUE.put(data_out)
|
SOCKET_QUEUE.put(data_out)
|
||||||
|
|
|
@ -5,7 +5,7 @@ Created on Wed Dec 23 11:13:57 2020
|
||||||
|
|
||||||
@author: DJ2LS
|
@author: DJ2LS
|
||||||
Here we are saving application wide variables and stats, which have to be accessed everywhere.
|
Here we are saving application wide variables and stats, which have to be accessed everywhere.
|
||||||
Not nice, suggestions are appreciated :-)
|
Not nice, suggestions are appreciated :-)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = '0.4.0-alpha'
|
VERSION = '0.4.0-alpha'
|
||||||
|
@ -55,7 +55,7 @@ HAMLIB_HANDSHAKE = 'None'
|
||||||
HAMLIB_RADIOCONTROL = 'direct'
|
HAMLIB_RADIOCONTROL = 'direct'
|
||||||
HAMLIB_RIGCTLD_IP = '127.0.0.1'
|
HAMLIB_RIGCTLD_IP = '127.0.0.1'
|
||||||
HAMLIB_RIGCTLD_PORT = '4532'
|
HAMLIB_RIGCTLD_PORT = '4532'
|
||||||
|
|
||||||
HAMLIB_FREQUENCY = 0
|
HAMLIB_FREQUENCY = 0
|
||||||
HAMLIB_MODE = ''
|
HAMLIB_MODE = ''
|
||||||
HAMLIB_BANDWITH = 0
|
HAMLIB_BANDWITH = 0
|
||||||
|
@ -122,4 +122,4 @@ INFO = []
|
||||||
|
|
||||||
# ------- CODEC2 SETTINGS
|
# ------- CODEC2 SETTINGS
|
||||||
TUNING_RANGE_FMIN = -50.0
|
TUNING_RANGE_FMIN = -50.0
|
||||||
TUNING_RANGE_FMAX = 50.0
|
TUNING_RANGE_FMAX = 50.0
|
||||||
|
|
Loading…
Reference in a new issue