mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
minor modem change
problems can occur. changed modem to simultaneous decoding. socket now multithreaded. huge code cleanup neccesary
This commit is contained in:
parent
5ad17d5b5b
commit
b813e8562c
|
@ -120,48 +120,6 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
|
|||
pttport = received_json["parameter"][0]["pttport"]
|
||||
print("---- STARTING TNC !")
|
||||
print(received_json["parameter"][0])
|
||||
#os.system("python3 main.py --rx 3 --tx 3 --deviceport /dev/ttyUSB0 --deviceid 2028")
|
||||
|
||||
|
||||
# Start RIGCTLD
|
||||
|
||||
if pttprotocol == "RTS":
|
||||
dtr_state = "OFF"
|
||||
elif pttprotocol == "DTR":
|
||||
dtr_state = "OFF"
|
||||
else:
|
||||
dtr_state = "OFF"
|
||||
|
||||
|
||||
if sys.platform == "linux":
|
||||
# we need to make sure we have execution privileges
|
||||
p = subprocess.Popen("chmod +x ./hamlib/linux/rigctld", shell=True)
|
||||
#run hamlib rigctld network service
|
||||
command = "exec ./hamlib/linux/rigctld -r " + str(deviceport) + \
|
||||
" -s "+ str(serialspeed) + \
|
||||
" -P "+ str(pttprotocol) + \
|
||||
" -m "+ str(deviceid) + \
|
||||
" --set-conf=dtr_state=" + dtr_state
|
||||
try:
|
||||
p = subprocess.Popen(command, shell=True)
|
||||
time.sleep(0.3)
|
||||
except:
|
||||
print("hamlib not started")
|
||||
sys.exit()
|
||||
|
||||
elif sys.platform == "darwin":
|
||||
print("platform not yet supported")
|
||||
sys.exit()
|
||||
|
||||
elif sys.platform == "win32":
|
||||
print("platform not yet supported")
|
||||
sys.exit()
|
||||
|
||||
else:
|
||||
print("platform not supported!")
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
command = "--rx "+ str(rx_audio) +" \
|
||||
--tx "+ str(tx_audio) +" \
|
||||
|
|
|
@ -16,14 +16,13 @@ import sys
|
|||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
# --------------------------------------------GET PARAMETER INPUTS
|
||||
PARSER = argparse.ArgumentParser(description='Simons TEST TNC')
|
||||
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('--port', dest="socket_port", default=3000, help="Socket port", type=int)
|
||||
PARSER.add_argument('--deviceport', dest="hamlib_device_port", default="/dev/ttyUSB0", help="Socket port", type=str)
|
||||
PARSER.add_argument('--deviceid', dest="hamlib_device_id", default=3011, help="Socket port", type=str)
|
||||
PARSER.add_argument('--deviceid', dest="hamlib_device_id", default=2028, help="Socket port", type=str)
|
||||
PARSER.add_argument('--serialspeed', dest="hamlib_serialspeed", default=9600, help="Serialspeed", type=str)
|
||||
PARSER.add_argument('--pttprotocol', dest="hamlib_ptt_type", default='RTS', help="PTT Type", type=str)
|
||||
PARSER.add_argument('--pttport', dest="hamlib_ptt_port", default="/dev/ttyUSB0", help="PTT Port", type=str)
|
||||
|
|
227
tnc/modem.py
227
tnc/modem.py
|
@ -98,21 +98,16 @@ class RF():
|
|||
self.streambuffer = bytes(0)
|
||||
self.audio_writing_to_stream = False
|
||||
# --------------------------------------------START DECODER THREAD
|
||||
FREEDV_DECODER_THREAD_10 = threading.Thread(target=self.receive, args=[10], name="FREEDV_DECODER_THREAD_10")
|
||||
FREEDV_DECODER_THREAD_10.start()
|
||||
|
||||
#FREEDV_DECODER_THREAD_11 = threading.Thread(target=self.receive, args=[11], name="FREEDV_DECODER_THREAD_11")
|
||||
#FREEDV_DECODER_THREAD_11.start()
|
||||
DECODER_THREAD = threading.Thread(target=self.receive, name="DECODER_THREAD")
|
||||
DECODER_THREAD.start()
|
||||
|
||||
FREEDV_DECODER_THREAD_12 = threading.Thread(target=self.receive, args=[12], name="FREEDV_DECODER_THREAD_12")
|
||||
FREEDV_DECODER_THREAD_12.start()
|
||||
|
||||
FREEDV_DECODER_THREAD_14 = threading.Thread(target=self.receive, args=[static.FREEDV_SIGNALLING_MODE], name="FREEDV_DECODER_THREAD_14")
|
||||
FREEDV_DECODER_THREAD_14.start()
|
||||
|
||||
FREEDV_PLAYBACK_THREAD = threading.Thread(target=self.play_audio, name="FREEDV_DECODER_THREAD_14")
|
||||
FREEDV_PLAYBACK_THREAD.start()
|
||||
PLAYBACK_THREAD = threading.Thread(target=self.play_audio, name="PLAYBACK_THREAD")
|
||||
PLAYBACK_THREAD.start()
|
||||
|
||||
#self.fft_data = bytes()
|
||||
#FFT_THREAD = threading.Thread(target=self.calculate_fft, args=[self.fft_data], name="FFT_THREAD")
|
||||
#FFT_THREAD.start()
|
||||
# --------------------------------------------CONFIGURE HAMLIB
|
||||
|
||||
print(static.HAMLIB_PTT_TYPE)
|
||||
|
@ -166,10 +161,14 @@ class RF():
|
|||
|
||||
self.my_rig.open()
|
||||
atexit.register(self.my_rig.close)
|
||||
|
||||
|
||||
|
||||
# set rig mode to USB
|
||||
self.my_rig.set_mode(Hamlib.RIG_MODE_USB)
|
||||
|
||||
# start thread for getting hamlib data
|
||||
HAMLIB_THREAD = threading.Thread(target=self.get_radio_stats, name="HAMLIB_THREAD")
|
||||
HAMLIB_THREAD.start()
|
||||
|
||||
except:
|
||||
print("Unexpected error:", sys.exc_info()[0])
|
||||
print("can't open rig")
|
||||
|
@ -436,21 +435,52 @@ class RF():
|
|||
self.c_lib.freedv_close(freedv)
|
||||
# --------------------------------------------------------------------------------------------------------
|
||||
|
||||
def receive(self, mode):
|
||||
force = False
|
||||
|
||||
# create new codec2 instance
|
||||
def receive(self):
|
||||
|
||||
# DATAC0
|
||||
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
|
||||
freedv = self.c_lib.freedv_open(mode)
|
||||
bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(freedv) / 8)
|
||||
datac0_freedv = self.c_lib.freedv_open(14)
|
||||
self.c_lib.freedv_get_bits_per_modem_frame(datac0_freedv)
|
||||
datac0_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac0_freedv)/8)
|
||||
datac0_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac0_freedv)
|
||||
|
||||
datac0_bytes_out = (ctypes.c_ubyte * datac0_bytes_per_frame) #bytes_per_frame
|
||||
datac0_bytes_out = datac0_bytes_out() #get pointer from bytes_out
|
||||
|
||||
self.c_lib.freedv_set_frames_per_burst(datac0_freedv,1)
|
||||
datac0_modem_stats_snr = c_float()
|
||||
datac0_modem_stats_sync = c_int()
|
||||
datac0_buffer = bytes()
|
||||
|
||||
static.FREEDV_SIGNALLING_BYTES_PER_FRAME = datac0_bytes_per_frame
|
||||
static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = datac0_bytes_per_frame - 2
|
||||
|
||||
if mode == static.FREEDV_SIGNALLING_MODE:
|
||||
static.FREEDV_SIGNALLING_BYTES_PER_FRAME = bytes_per_frame
|
||||
static.FREEDV_SIGNALLING_PAYLOAD_PER_FRAME = bytes_per_frame - 2
|
||||
# DATAC1
|
||||
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
|
||||
datac1_freedv = self.c_lib.freedv_open(10)
|
||||
datac1_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac1_freedv)/8)
|
||||
datac1_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac1_freedv)
|
||||
datac1_bytes_out = (ctypes.c_ubyte * datac1_bytes_per_frame) #bytes_per_frame
|
||||
datac1_bytes_out = datac1_bytes_out() #get pointer from bytes_out
|
||||
self.c_lib.freedv_set_frames_per_burst(datac1_freedv,1)
|
||||
datac1_modem_stats_snr = c_float()
|
||||
datac1_modem_stats_sync = c_int()
|
||||
datac1_buffer = bytes()
|
||||
|
||||
self.c_lib.freedv_set_frames_per_burst(freedv, 1)
|
||||
# DATAC3
|
||||
self.c_lib.freedv_open.restype = ctypes.POINTER(ctypes.c_ubyte)
|
||||
datac3_freedv = self.c_lib.freedv_open(12)
|
||||
datac3_bytes_per_frame = int(self.c_lib.freedv_get_bits_per_modem_frame(datac3_freedv)/8)
|
||||
datac3_n_max_modem_samples = self.c_lib.freedv_get_n_max_modem_samples(datac3_freedv)
|
||||
datac3_bytes_out = (ctypes.c_ubyte * datac3_bytes_per_frame) #bytes_per_frame
|
||||
datac3_bytes_out = datac3_bytes_out() #get pointer from bytes_out
|
||||
self.c_lib.freedv_set_frames_per_burst(datac3_freedv,1)
|
||||
datac3_modem_stats_snr = c_float()
|
||||
datac3_modem_stats_sync = c_int()
|
||||
datac3_buffer = bytes()
|
||||
|
||||
elif mode == static.ARQ_DATA_CHANNEL_MODE:
|
||||
'''
|
||||
if mode == static.ARQ_DATA_CHANNEL_MODE:
|
||||
static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame
|
||||
static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2
|
||||
|
||||
|
@ -458,49 +488,112 @@ class RF():
|
|||
else:
|
||||
#pass
|
||||
self.c_lib.freedv_set_frames_per_burst(freedv, 0)
|
||||
|
||||
bytes_out = (ctypes.c_ubyte * bytes_per_frame)
|
||||
bytes_out = bytes_out() # get pointer to bytes_out
|
||||
'''
|
||||
|
||||
while static.FREEDV_RECEIVE == True:
|
||||
time.sleep(0.01)
|
||||
|
||||
'''
|
||||
# refresh vars, so the correct parameters of the used mode are set
|
||||
if mode == static.ARQ_DATA_CHANNEL_MODE:
|
||||
static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame
|
||||
static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2
|
||||
'''
|
||||
|
||||
data_in = bytes()
|
||||
data_in = self.stream_rx.read(1024, exception_on_overflow = False)
|
||||
data_in = audioop.ratecv(data_in,2,1,static.AUDIO_SAMPLE_RATE_RX, static.MODEM_SAMPLE_RATE, None)
|
||||
data_in = data_in[0]#.rstrip(b'\x00')
|
||||
self.fft_data = data_in[0]
|
||||
|
||||
# lets get the frequency, mode and bandwith
|
||||
self.get_radio_stats()
|
||||
# we need to set nin * 2 beause of byte size in array handling
|
||||
datac0_nin = self.c_lib.freedv_nin(datac0_freedv) * 2
|
||||
datac1_nin = self.c_lib.freedv_nin(datac1_freedv) * 2
|
||||
datac3_nin = self.c_lib.freedv_nin(datac3_freedv) * 2
|
||||
|
||||
# demod loop
|
||||
while (static.CHANNEL_STATE == 'RECEIVING_DATA' and static.ARQ_DATA_CHANNEL_MODE == mode) or (static.CHANNEL_STATE == 'RECEIVING_SIGNALLING' and static.FREEDV_SIGNALLING_MODE == mode):
|
||||
time.sleep(0.01)
|
||||
|
||||
# refresh vars, so the correct parameters of the used mode are set
|
||||
if mode == static.ARQ_DATA_CHANNEL_MODE:
|
||||
static.FREEDV_DATA_BYTES_PER_FRAME = bytes_per_frame
|
||||
static.FREEDV_DATA_PAYLOAD_PER_FRAME = bytes_per_frame - 2
|
||||
|
||||
nin = self.c_lib.freedv_nin(freedv)
|
||||
nin = int(nin*(static.AUDIO_SAMPLE_RATE_RX/static.MODEM_SAMPLE_RATE))
|
||||
# refill buffer only if every mode has worked with its data
|
||||
if (len(datac0_buffer) < (datac0_nin*2)) and (len(datac1_buffer) < (datac1_nin*2)) and (len(datac3_buffer) < (datac3_nin*2)):
|
||||
datac0_buffer += data_in
|
||||
datac1_buffer += data_in
|
||||
datac3_buffer += data_in
|
||||
|
||||
data_in = self.stream_rx.read(nin, exception_on_overflow=False)
|
||||
|
||||
data_in = audioop.ratecv(data_in,2,1,static.AUDIO_SAMPLE_RATE_RX, static.MODEM_SAMPLE_RATE, None)
|
||||
data_in = data_in[0]
|
||||
|
||||
static.AUDIO_RMS = audioop.rms(data_in, 2)
|
||||
nbytes = self.c_lib.freedv_rawdatarx(freedv, bytes_out, data_in) # demodulate audio
|
||||
#print("listening-" + str(mode) + " - " + "nin: " + str(nin) + " - " + str(self.c_lib.freedv_get_rx_status(freedv)))
|
||||
|
||||
|
||||
|
||||
# DECODING DATAC0
|
||||
if len(datac0_buffer) >= (datac0_nin):
|
||||
|
||||
datac0_audio = datac0_buffer[:datac0_nin]
|
||||
datac0_buffer = datac0_buffer[datac0_nin:]
|
||||
#print(len(datac0_audio))
|
||||
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac0_bytes_out, datac0_audio]
|
||||
nbytes = self.c_lib.freedv_rawdatarx(datac0_freedv, datac0_bytes_out, datac0_audio) # demodulate audio
|
||||
sync = self.c_lib.freedv_get_rx_status(datac0_freedv)
|
||||
if sync != 0 and nbytes != 0:
|
||||
|
||||
#calculate snr and scatter
|
||||
self.get_scatter(datac0_freedv)
|
||||
self.calculate_snr(datac0_freedv)
|
||||
|
||||
datac0_task = threading.Thread(target=self.process_data, args=[datac0_bytes_out, datac0_freedv])
|
||||
datac0_task.start()
|
||||
|
||||
|
||||
|
||||
# DECODING DATAC1
|
||||
if len(datac1_buffer) >= (datac1_nin):
|
||||
datac1_audio = datac1_buffer[:datac1_nin]
|
||||
datac1_buffer = datac1_buffer[datac1_nin:]
|
||||
#print(len(datac1_audio))
|
||||
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac1_bytes_out, datac1_audio]
|
||||
nbytes = self.c_lib.freedv_rawdatarx(datac1_freedv, datac1_bytes_out, datac1_audio) # demodulate audio
|
||||
|
||||
sync = self.c_lib.freedv_get_rx_status(datac1_freedv)
|
||||
if sync != 0 and nbytes != 0:
|
||||
|
||||
#calculate snr and scatter
|
||||
self.get_scatter(datac1_freedv)
|
||||
self.calculate_snr(datac1_freedv)
|
||||
|
||||
datac1_task = threading.Thread(target=self.process_data, args=[datac1_bytes_out, datac1_freedv])
|
||||
datac1_task.start()
|
||||
|
||||
# DECODING DATAC3
|
||||
if len(datac3_buffer) >= (datac3_nin):
|
||||
datac3_audio = datac3_buffer[:datac3_nin]
|
||||
datac3_buffer = datac3_buffer[datac3_nin:]
|
||||
self.c_lib.freedv_rawdatarx.argtype = [ctypes.POINTER(ctypes.c_ubyte), datac3_bytes_out, datac3_audio]
|
||||
nbytes = self.c_lib.freedv_rawdatarx(datac3_freedv, datac3_bytes_out, datac3_audio) # demodulate audio
|
||||
|
||||
sync = self.c_lib.freedv_get_rx_status(datac3_freedv)
|
||||
if sync != 0 and nbytes != 0:
|
||||
|
||||
#calculate snr and scatter
|
||||
self.get_scatter(datac3_freedv)
|
||||
self.calculate_snr(datac3_freedv)
|
||||
|
||||
datac3_task = threading.Thread(target=self.process_data, args=[datac3_bytes_out, datac3_freedv])
|
||||
datac3_task.start()
|
||||
|
||||
|
||||
###### THIS FUNCTIONS NEED TO MOVE TO AN OWN FUNCTION WITHIN AN OWN THREAD!
|
||||
# get scatter data, fft and snr data
|
||||
self.get_scatter(freedv)
|
||||
self.calculate_snr(freedv)
|
||||
#self.get_scatter(datac0_freedv)
|
||||
#self.calculate_snr(datac0_freedv)
|
||||
#self.get_scatter(datac1_freedv)
|
||||
#self.calculate_snr(datac1_freedv)
|
||||
#self.get_scatter(datac3_freedv)
|
||||
#self.calculate_snr(datac3_freedv)
|
||||
|
||||
self.calculate_fft(data_in)
|
||||
|
||||
# forward data only if broadcast or we are the receiver
|
||||
# bytes_out[1:2] == callsign check for signalling frames, bytes_out[6:7] == callsign check for data frames, bytes_out[1:2] == b'\x01' --> broadcasts like CQ
|
||||
# we could also create an own function, which returns True. In this case we could add callsign blacklists and so on
|
||||
if nbytes == bytes_per_frame and bytes(bytes_out[1:2]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[6:7]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[1:2]) == b'\x01':
|
||||
|
||||
self.calculate_snr(freedv)
|
||||
|
||||
def process_data(self, bytes_out, freedv):
|
||||
force = True
|
||||
print(bytes(bytes_out))
|
||||
if bytes(bytes_out[1:2]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[6:7]) == static.MYCALLSIGN_CRC8 or bytes(bytes_out[1:2]) == b'\x01':
|
||||
|
||||
helpers.calculate_transfer_rate()
|
||||
# CHECK IF FRAMETYPE IS BETWEEN 10 and 50 ------------------------
|
||||
frametype = int.from_bytes(bytes(bytes_out[:1]), "big")
|
||||
|
@ -592,25 +685,24 @@ class RF():
|
|||
logging.info("OTHER FRAME: " + str(bytes_out[:-2]))
|
||||
print(frametype)
|
||||
|
||||
# DO UNSYNC AFTER LAST BURST by checking the frame nums agains the total frames per burst
|
||||
# DO UNSYNC AFTER LAST BURST by checking the frame nums against the total frames per burst
|
||||
if frame == n_frames_per_burst:
|
||||
|
||||
logging.debug("LAST FRAME ---> UNSYNC")
|
||||
|
||||
bytes_out = (ctypes.c_ubyte * bytes_per_frame)
|
||||
bytes_out = bytes_out() # get pointer to bytes_out
|
||||
|
||||
|
||||
self.c_lib.freedv_set_sync(freedv, 0) # FORCE UNSYNC
|
||||
|
||||
# clear bytes_out buffer to be ready for next frames after successfull decoding
|
||||
|
||||
bytes_out = (ctypes.c_ubyte * bytes_per_frame)
|
||||
bytes_out = bytes_out() # get pointer to bytes_out
|
||||
#bytes_out = (ctypes.c_ubyte * bytes_per_frame)
|
||||
#bytes_out = bytes_out() # get pointer to bytes_out
|
||||
|
||||
else:
|
||||
# for debugging purposes to receive all data
|
||||
pass
|
||||
# print(bytes_out[:-2])
|
||||
else:
|
||||
# for debugging purposes to receive all data
|
||||
pass
|
||||
# print(bytes_out[:-2])
|
||||
|
||||
|
||||
def get_scatter(self, freedv):
|
||||
modemStats = MODEMSTATS()
|
||||
self.c_lib.freedv_get_modem_extended_stats.restype = None
|
||||
|
@ -664,6 +756,7 @@ class RF():
|
|||
|
||||
|
||||
def calculate_fft(self, data_in):
|
||||
|
||||
# WE NEED TO OPTIMIZE THIS!
|
||||
|
||||
|
||||
|
|
23
tnc/sock.py
23
tnc/sock.py
|
@ -35,7 +35,11 @@ import helpers
|
|||
|
||||
import sys, os
|
||||
|
||||
class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
|
||||
|
||||
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||
pass
|
||||
|
||||
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
print("Client connected...")
|
||||
|
@ -52,6 +56,7 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler):
|
|||
|
||||
# we need to loop through buffer until end of chunk is reached or timeout occured
|
||||
while True and socketTimeout > time.time():
|
||||
|
||||
chunk = self.request.recv(1024) # .strip()
|
||||
data += chunk
|
||||
if chunk.endswith(b'}\n'):# or chunk.endswith(b'}') or chunk.endswith(b'\n'):
|
||||
|
@ -246,8 +251,16 @@ def start_cmd_socket():
|
|||
try:
|
||||
logging.info("SRV | STARTING TCP/IP SOCKET FOR CMD ON PORT: " + str(static.PORT))
|
||||
socketserver.TCPServer.allow_reuse_address = True # https://stackoverflow.com/a/16641793
|
||||
cmdserver = socketserver.TCPServer((static.HOST, static.PORT), CMDTCPRequestHandler)
|
||||
cmdserver.serve_forever()
|
||||
cmdserver = ThreadedTCPServer((static.HOST, static.PORT), ThreadedTCPRequestHandler)
|
||||
server_thread = threading.Thread(target=cmdserver.serve_forever)
|
||||
server_thread.daemon = True
|
||||
server_thread.start()
|
||||
|
||||
finally:
|
||||
cmdserver.server_close()
|
||||
|
||||
except:
|
||||
print("Socket error...")
|
||||
e = sys.exc_info()[0]
|
||||
print(e)
|
||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
|
||||
print(exc_type, fname, exc_tb.tb_lineno)
|
||||
|
|
Loading…
Reference in a new issue