From 319de5cf42807f5bb2487bd7670d56cdb7df77d3 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Fri, 1 Apr 2022 00:46:34 -0400 Subject: [PATCH] Initial changes to handle GQRX process --- BotResources.py | 8 ++++ bot.py | 12 ++++- gqrxHandler.py | 121 +++++++++++++++++++++++++++++++++++++++++++++--- op25Handler.py | 2 +- 4 files changed, 134 insertions(+), 9 deletions(-) diff --git a/BotResources.py b/BotResources.py index b8b8c43..a87ea78 100644 --- a/BotResources.py +++ b/BotResources.py @@ -5,18 +5,26 @@ from datetime import date from os.path import exists from NoiseGatev2 import AudioStream +# Handler configs PDB_ACCEPTABLE_HANDLERS = {'gqrx': { 'Modes': ['wfm', 'fm'] }, 'op25': { 'Modes': ['d', 'p25'] }} + +# Known bot IDs PDB_KNOWN_BOT_IDS = {756327271597473863: "Greada", 915064996994633729: "Jorn", 943742040255115304: "Brent"} +# Default value to set noisegate on new or unknown profiles DEFAULT_NOISEGATE_THRESHOLD = 50 +# Initialize the logger for this file LOGGER = logging.getLogger('Discord_Radio_Bot.Bot_Resources') +# Location of the gqrx binary +GQRX_BIN_LOCATION = "/usr/bin/" +GQRX_BIN = "/usr/bin/gqrx" def check_if_config_exists(): if exists('./config.ini'): diff --git a/bot.py b/bot.py index c33f2b6..143a53a 100644 --- a/bot.py +++ b/bot.py @@ -338,6 +338,7 @@ class Bot(commands.Bot): self.logger.info("Starting GQRX handler") from gqrxHandler import GQRXHandler self.GQRXHandler = GQRXHandler() + self.GQRXHandler.start() self.possible_modes = BotResources.PDB_ACCEPTABLE_HANDLERS['gqrx']['Modes'] elif self.Handler == 'op25': @@ -435,7 +436,9 @@ class Bot(commands.Bot): if self.Handler == 'gqrx': # Set the settings in GQRX - self.GQRXHandler.set_all_settings(self.mode, self.squelch, self.freq) + self.GQRXHandler.set_gqrx_parameters(_frequency=self.freq, _squelch=self.squelch, + _fm_mode=self.mode, _output_device_name=self.DEVICE_NAME, + _start=True) elif self.Handler == 'op25': self.OP25Handler.set_op25_parameters(self.freq, _start=True, _output_device_name=self.DEVICE_NAME) @@ -447,11 +450,16 @@ class Bot(commands.Bot): def stop_sdr(self): if self.sdr_started: # Wait for the running processes to close + + # Close the GQRX handler + if self.Handler == 'gqrx': + self.GQRXHandler.set_gqrx_parameters(_stop=True) + # Close the OP25 handler if self.Handler == 'op25': self.OP25Handler.set_op25_parameters(_stop=True) # self.OP25Handler.join() - # Need a way to 'close' GQRX + self.sdr_started = False # Set the activity of the bot diff --git a/gqrxHandler.py b/gqrxHandler.py index 2727a13..58a1f4b 100644 --- a/gqrxHandler.py +++ b/gqrxHandler.py @@ -1,18 +1,114 @@ +import shutil import logging +import threading +import subprocess from telnetlib import Telnet -from BotResources import check_negative +from BotResources import * from time import sleep -class GQRXHandler(): - def __init__(self, hostname: str = "localhost", port: int = 7356): - self.logger = logging.getLogger("Discord_Radio_Bot.GQRXHandler") - self.hostname = hostname - self.port = port +class GQRXHandler(threading.Thread): + def __init__(self): + super().__init__() + self.GQRXDir: str = GQRX_BIN_LOCATION + self.GQRXEXE: str = shutil.which(GQRX_BIN) + self.GQRXProc = None + + self.Frequency = None + + self.Mode = None + self.Frequency = None + self.Squelch = None + + self.Start_GQRX = False + self.Stop_GQRX = False + + self.Output_Device_Name = None + + self.hostname = "localhost" + self.port = 7356 self.tel_conn = None + self.open_gqrx() + self.create_telnet_connection() + self.logger = logging.getLogger("Discord_Radio_Bot.GQRXHandler") + + def run(self) -> None: + while True: + if self.Start_GQRX: + self.open_gqrx() + + self.Start_GQRX = False + self.Stop_GQRX = False + + while not self.Stop_GQRX: + sleep(1) + + self.close_gqrx() + + sleep(.5) + + def set_gqrx_parameters(self, _frequency: str = False, _start: bool = False, _stop: bool = False, + _output_device_name: str = None, _fm_mode: str = None, _squelch: int = None, + _hostname: str = None, _port: int = None): + if _frequency: + self.Frequency = _frequency + + if _output_device_name: + self.Output_Device_Name = _output_device_name + + if _fm_mode: + self.Mode = _fm_mode + + if _squelch: + self.Squelch = _squelch + + if _hostname: + self.hostname = _hostname + self.Start_GQRX = True + + if _port: + self.port = _port + self.Start_GQRX = True + + if _start: + self.Start_GQRX = _start + + if _stop: + self.Stop_GQRX = _stop + + def open_gqrx(self): + if self.GQRXProc is not None: + self.close_gqrx() + + gqrx_kwargs = [f""] + + self.logger.info(f"Starting GQRX") + + self.logger.debug(f"GQRX Keyword Args: {gqrx_kwargs}") + + self.GQRXProc = subprocess.Popen(gqrx_kwargs, executable=self.GQRXEXE, shell=False, cwd=self.GQRXDir) + + def close_gqrx(self): + self.logger.info(f"Closing GQRX") + try: + self.GQRXProc.kill() + + seconds_waited = 0 + while self.GQRXProc.poll() is None: + # Terminate the process every 5 seconds + if seconds_waited % 5 == 0: + self.logger.info("Terminating GQRX") + self.GQRXProc.terminate() + sleep(1) + self.logger.debug(f"Waited {seconds_waited} seconds") + seconds_waited += 1 + + except Exception as e: + self.logger.error(e) + def create_telnet_connection(self): self.logger.info("Creating connection") self.tel_conn = Telnet(self.hostname, self.port) @@ -23,6 +119,19 @@ class GQRXHandler(): self.tel_conn.write(bytes(f"F {int(freq)}", 'utf-8')) self.tel_conn.read_until(b'RPRT 0') + def check_dsp(self): + self.logger.debug(f"Checking if DSP is running on GQRX") + self.tel_conn.write(bytes(f"u DSP", 'utf-8')) + if self.tel_conn.read_some() == b"1": + return True + else: + return False + + def start_dsp(self): + self.logger.debug(f"Starting DSP on GQRX") + self.tel_conn.write(bytes(f"U DSP 1", 'utf-8')) + self.tel_conn.read_until(b'RPRT 0') + def change_squelch(self, squelch): if not check_negative(squelch): squelch = float(-abs(squelch)) diff --git a/op25Handler.py b/op25Handler.py index 947f62a..1c828cf 100644 --- a/op25Handler.py +++ b/op25Handler.py @@ -81,7 +81,7 @@ class OP25Handler(threading.Thread): while self.OP25Proc.poll() is None: # Terminate the process every 5 seconds if seconds_waited % 5 == 0: - self.logger.debug("Terminating OP25") + self.logger.info("Terminating OP25") self.OP25Proc.terminate() time.sleep(1) self.logger.debug(f"Waited {seconds_waited} seconds")