Compare commits
37 Commits
31d5f8139c
...
b2a73726a0
| Author | SHA1 | Date | |
|---|---|---|---|
| b2a73726a0 | |||
|
|
a094ba581d | ||
|
|
62f9e1abaa | ||
|
|
e4e04e429f | ||
|
|
0db4f62afc | ||
|
|
4d5c1183d6 | ||
|
|
9dba89a60b | ||
|
|
dcf0de8351 | ||
|
|
bfb049e268 | ||
|
|
b0d83def35 | ||
|
|
8af7a70b65 | ||
|
|
8d090c5c67 | ||
|
|
35e19ee83f | ||
|
|
44d027ab8c | ||
|
|
3837f7abd6 | ||
|
|
b7f0939787 | ||
|
|
cccd974adc | ||
|
|
f4b14c26fc | ||
|
|
a483f83b4b | ||
|
|
458ab5be95 | ||
|
|
dbbd5b6fe3 | ||
|
|
63b37d14cb | ||
|
|
2dabf1c98d | ||
|
|
5551aa6355 | ||
|
|
7ee5d92852 | ||
|
|
5a3729627b | ||
|
|
bb56566d37 | ||
|
|
99ec1d07aa | ||
|
|
bbca25ce3f | ||
|
|
676936eb6f | ||
|
|
8debd690f1 | ||
|
|
5d1a58ee87 | ||
|
|
fd62da0c6f | ||
|
|
b972d09a65 | ||
|
|
21aacde130 | ||
|
|
e26ae52399 | ||
|
|
319de5cf42 |
@@ -5,18 +5,37 @@ 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"
|
||||
|
||||
|
||||
# Default radio settings
|
||||
DEFAULT_RADIO_SETTINGS = {
|
||||
'profile_name': None,
|
||||
'freq': "104700000",
|
||||
'mode': "wfm",
|
||||
'squelch': 0,
|
||||
'noisegate_sensitivity': DEFAULT_NOISEGATE_THRESHOLD,
|
||||
}
|
||||
|
||||
|
||||
def check_if_config_exists():
|
||||
if exists('./config.ini'):
|
||||
|
||||
@@ -167,7 +167,10 @@ class NoiseGateStream(discord.AudioSource):
|
||||
buffer_decibel = 20 * math.log10(buffer_rms)
|
||||
|
||||
if self.process_set_count % 10 == 0:
|
||||
LOGGER.debug(f"{buffer_decibel} db")
|
||||
if buffer_decibel >= self.stream.THRESHOLD:
|
||||
LOGGER.debug(f"[Noisegate Open] {buffer_decibel} db")
|
||||
else:
|
||||
LOGGER.debug(f"[Noisegate Closed] {buffer_decibel} db")
|
||||
|
||||
if buffer_decibel >= self.stream.THRESHOLD:
|
||||
self.NG_fadeout_count = self.NG_fadeout
|
||||
|
||||
@@ -23,4 +23,9 @@ Voicemeeter is **highly** recommended for this bot. See a detailed guide on how
|
||||
To change the audio source, simply delete the ```config.ini``` that was generated and restart the bot.
|
||||
It will re-do the setup and allow you to select a new device.
|
||||
|
||||
### [To-Do](https://git.vpn.cusano.net/Discord_Bot_Gang/Discord-Radio-Bot/src/branch/master/TODO.md)
|
||||
### [To-Do](https://git.vpn.cusano.net/Discord_Bot_Gang/Discord-Radio-Bot/src/branch/master/TODO.md)
|
||||
|
||||
|
||||
**Notes for readme leter on**
|
||||
- Users need to save profile after any change in discord
|
||||
-
|
||||
1
TODO.md
1
TODO.md
@@ -3,6 +3,7 @@
|
||||
### Main Development
|
||||
#### Core
|
||||
- [ ] Add new handlers for GQRX: https://github.com/gqrx-sdr/gqrx/blob/master/resources/remote-control.txt
|
||||
- [ ] Add logging for Elasticstack https://www.elastic.co/guide/en/ecs-logging/python/master/installation.html
|
||||
- [ ] Add a process handler to start/stop gqrx
|
||||
- [ ] Fix the bug where they *disconnect* after a period of time and must be manually moved out and back in to hear them
|
||||
- *May* have been fixed with the noise gate?
|
||||
|
||||
60
bot.py
60
bot.py
@@ -42,11 +42,11 @@ class Bot(commands.Bot):
|
||||
_display_output_devices=False)
|
||||
|
||||
# Init radio parameters
|
||||
self.profile_name = None
|
||||
self.freq = "104700000"
|
||||
self.mode = "wfm"
|
||||
self.squelch = 0
|
||||
self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD
|
||||
self.profile_name = BotResources.DEFAULT_RADIO_SETTINGS['profile_name']
|
||||
self.freq = BotResources.DEFAULT_RADIO_SETTINGS['freq']
|
||||
self.mode = BotResources.DEFAULT_RADIO_SETTINGS['mode']
|
||||
self.squelch = BotResources.DEFAULT_RADIO_SETTINGS['squelch']
|
||||
self.noisegate_sensitivity = BotResources.DEFAULT_RADIO_SETTINGS['noisegate_sensitivity']
|
||||
|
||||
# Init SDR Variables
|
||||
self.system_os_type = None
|
||||
@@ -173,8 +173,12 @@ class Bot(commands.Bot):
|
||||
f"{self.streamHandler.THRESHOLD} to {_threshold}")
|
||||
self.streamHandler.THRESHOLD = _threshold
|
||||
self.noisegate_sensitivity = _threshold
|
||||
if self.sdr_started:
|
||||
await self.set_activity()
|
||||
|
||||
# Reset the profile name since we have made a change
|
||||
self.profile_name = None
|
||||
|
||||
# If the SDR is started, restart it with the updates
|
||||
await self.use_current_radio_config()
|
||||
|
||||
# Add commands for GQRX and OP25
|
||||
if self.Handler in BotResources.PDB_ACCEPTABLE_HANDLERS.keys():
|
||||
@@ -225,13 +229,11 @@ class Bot(commands.Bot):
|
||||
await ctx.send(f"Ok {str(member).capitalize()}, I'm changing the mode to "
|
||||
f"{str(self.mode).upper()} and frequency to {self.freq}")
|
||||
|
||||
# Reset the profile name since we have made a change to the freq
|
||||
# Reset the profile name since we have made a change
|
||||
self.profile_name = None
|
||||
|
||||
# If the SDR is started, restart it with the updates
|
||||
if self.sdr_started:
|
||||
self.start_sdr()
|
||||
await self.set_activity()
|
||||
await self.use_current_radio_config()
|
||||
else:
|
||||
await ctx.send(f"{str(member).capitalize()}, {mode} is not valid."
|
||||
f" You may only enter {self.possible_modes}")
|
||||
@@ -254,9 +256,11 @@ class Bot(commands.Bot):
|
||||
self.squelch = squelch
|
||||
await ctx.send(f"Ok {str(member).capitalize()}, I'm changing the squelch to {self.squelch}")
|
||||
|
||||
# Reset the profile name since we have made a change
|
||||
self.profile_name = None
|
||||
|
||||
# If the SDR is started, restart it with the updates
|
||||
if self.sdr_started:
|
||||
self.start_sdr()
|
||||
await self.use_current_radio_config()
|
||||
|
||||
# Hidden admin commands
|
||||
@self.command(name='saveprofile', hidden=True)
|
||||
@@ -338,6 +342,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 +440,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 +454,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
|
||||
@@ -497,8 +509,19 @@ class Bot(commands.Bot):
|
||||
|
||||
self.profile_name = profile_name
|
||||
|
||||
await self.use_current_radio_config()
|
||||
|
||||
async def use_current_radio_config(self):
|
||||
if self.sdr_started:
|
||||
self.start_sdr()
|
||||
# Set the loaded profile settings into GQRX
|
||||
if self.Handler == "gqrx":
|
||||
self.GQRXHandler.set_gqrx_parameters(_frequency=self.freq, _squelch=self.squelch,
|
||||
_fm_mode=self.mode)
|
||||
# Restart OP25 to use the loaded profile
|
||||
if self.Handler == "op25":
|
||||
self.start_sdr()
|
||||
|
||||
# Set the activity to reflect the loaded profile
|
||||
await self.set_activity()
|
||||
|
||||
# Load a saved profile into the current settings
|
||||
@@ -521,10 +544,7 @@ class Bot(commands.Bot):
|
||||
self.noisegate_sensitivity = BotResources.DEFAULT_NOISEGATE_THRESHOLD
|
||||
await self.save_radio_config(self.profile_name)
|
||||
|
||||
if self.sdr_started:
|
||||
self.start_sdr()
|
||||
await self.set_activity()
|
||||
|
||||
await self.use_current_radio_config()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
223
gqrxHandler.py
223
gqrxHandler.py
@@ -1,22 +1,195 @@
|
||||
import configparser
|
||||
import shutil
|
||||
import logging
|
||||
import threading
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
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):
|
||||
|
||||
def reset_crashed(_config_path):
|
||||
config = configparser.SafeConfigParser()
|
||||
config.read(_config_path)
|
||||
if config.has_section('General'):
|
||||
if config.getboolean('General', 'crashed'):
|
||||
config['General']['crashed'] = 'false'
|
||||
with open(_config_path, 'w') as config_file:
|
||||
config.write(config_file)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def enable_agc(_config_path):
|
||||
config = configparser.SafeConfigParser()
|
||||
config.read(_config_path)
|
||||
if config.has_option('receiver', 'agc_off'):
|
||||
config.remove_option('receiver', 'agc_off')
|
||||
with open(_config_path, 'w') as config_file:
|
||||
config.write(config_file)
|
||||
return True
|
||||
|
||||
|
||||
class GQRXHandler(threading.Thread):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.GQRX_Config_Path = Path(f"{Path.home()}/.config/gqrx/drb_defaults.conf")
|
||||
self.GQRXDir: str = GQRX_BIN_LOCATION
|
||||
self.GQRXEXE: str = shutil.which(GQRX_BIN)
|
||||
self.GQRXProc = None
|
||||
self.GQRX_Started = False
|
||||
|
||||
self.logger = logging.getLogger("Discord_Radio_Bot.GQRXHandler")
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
|
||||
self.Frequency = None
|
||||
|
||||
self.Mode = DEFAULT_RADIO_SETTINGS['mode']
|
||||
self.Frequency = DEFAULT_RADIO_SETTINGS['freq']
|
||||
self.Squelch = DEFAULT_RADIO_SETTINGS['squelch']
|
||||
|
||||
self.Start_GQRX = False
|
||||
self.Stop_GQRX = False
|
||||
|
||||
self.Output_Device_Name = None
|
||||
|
||||
self.hostname = "localhost"
|
||||
self.port = 7356
|
||||
|
||||
self.tel_conn = None
|
||||
|
||||
self.create_telnet_connection()
|
||||
def run(self) -> None:
|
||||
while True:
|
||||
if self.Start_GQRX:
|
||||
self.open_gqrx()
|
||||
|
||||
self.Start_GQRX = False
|
||||
self.Stop_GQRX = False
|
||||
|
||||
self.logger.debug("GQRX is open, waiting for it to close")
|
||||
|
||||
while not self.Stop_GQRX:
|
||||
sleep(1)
|
||||
|
||||
self.logger.debug('Request to close GQRX')
|
||||
|
||||
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: float = None,
|
||||
_hostname: str = None, _port: int = None, _start_dsp: bool = None):
|
||||
if _frequency:
|
||||
self.Frequency = _frequency
|
||||
if self.GQRX_Started:
|
||||
self.change_freq(_frequency)
|
||||
|
||||
if _output_device_name:
|
||||
self.Output_Device_Name = _output_device_name
|
||||
|
||||
if _fm_mode:
|
||||
self.Mode = _fm_mode
|
||||
if self.GQRX_Started:
|
||||
self.change_mode(_fm_mode)
|
||||
|
||||
if _squelch:
|
||||
self.Squelch = _squelch
|
||||
if self.GQRX_Started:
|
||||
self.change_squelch(_squelch)
|
||||
|
||||
if _hostname:
|
||||
self.hostname = _hostname
|
||||
self.Start_GQRX = True
|
||||
|
||||
if _port:
|
||||
self.port = _port
|
||||
self.Start_GQRX = True
|
||||
|
||||
if _start_dsp:
|
||||
self.start_dsp()
|
||||
|
||||
if _start:
|
||||
self.Start_GQRX = _start
|
||||
|
||||
if _stop:
|
||||
self.Stop_GQRX = _stop
|
||||
|
||||
def open_gqrx(self):
|
||||
if self.GQRX_Started:
|
||||
self.close_gqrx()
|
||||
|
||||
gqrx_kwargs = [f"gqrx", "-c", "drb_defaults.conf"]
|
||||
|
||||
self.logger.info(f"Resetting 'crashed' option in the GQRX config")
|
||||
|
||||
self.reset_or_create_config()
|
||||
|
||||
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)
|
||||
|
||||
while not self.tel_conn:
|
||||
self.create_telnet_connection()
|
||||
sleep(2)
|
||||
self.logger.debug(f"Waiting for GQRX to start")
|
||||
|
||||
self.GQRX_Started = True
|
||||
|
||||
self.start_dsp()
|
||||
|
||||
self.set_all_settings(_squelch=self.Squelch, _mode=self.Mode, _freq=self.Frequency)
|
||||
self.logger.debug('Finished opening GQRX')
|
||||
|
||||
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
|
||||
self.logger.debug("GQRX Closed")
|
||||
self.GQRX_Started = False
|
||||
self.tel_conn = None
|
||||
|
||||
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)
|
||||
self.tel_conn.open(self.hostname, self.port)
|
||||
self.logger.debug("Creating connection")
|
||||
try:
|
||||
self.tel_conn = Telnet(self.hostname, self.port)
|
||||
self.tel_conn.open(self.hostname, self.port)
|
||||
self.logger.debug(f"GQRX is open")
|
||||
return True
|
||||
except Exception as err:
|
||||
self.logger.warning(err)
|
||||
self.tel_conn = None
|
||||
return False
|
||||
|
||||
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):
|
||||
if not self.check_dsp():
|
||||
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_freq(self, freq):
|
||||
self.logger.debug(f"Changing freq to {freq}")
|
||||
@@ -35,8 +208,32 @@ class GQRXHandler():
|
||||
self.tel_conn.write(bytes(f"M {str(mode)}", 'utf-8'))
|
||||
self.tel_conn.read_until(b'RPRT 0')
|
||||
|
||||
def set_all_settings(self, mode, squelch, freq):
|
||||
def set_all_settings(self, _mode, _squelch, _freq):
|
||||
self.change_squelch(0)
|
||||
self.change_mode(mode)
|
||||
self.change_freq(freq)
|
||||
self.change_squelch(squelch)
|
||||
self.change_mode(_mode)
|
||||
self.change_freq(_freq)
|
||||
self.change_squelch(_squelch)
|
||||
|
||||
def creat_config(self):
|
||||
from templates.gqrx_config_template import drb_defaults
|
||||
config = drb_defaults
|
||||
try:
|
||||
with open(self.GQRX_Config_Path, 'w+') as config_file:
|
||||
config_file.write(config)
|
||||
except OSError as err:
|
||||
self.logger.error(err)
|
||||
|
||||
def reset_or_create_config(self):
|
||||
if self.GQRX_Config_Path.is_file():
|
||||
try:
|
||||
self.logger.debug(f"Enabling AGC in the GQRX config")
|
||||
enable_agc(_config_path=self.GQRX_Config_Path)
|
||||
|
||||
self.logger.debug(f"GQRX Config exists, resetting 'crashed' setting")
|
||||
reset_crashed(_config_path=self.GQRX_Config_Path)
|
||||
except configparser.DuplicateOptionError as err:
|
||||
self.logger.warning(err)
|
||||
self.creat_config()
|
||||
else:
|
||||
self.logger.debug(f"GQRX config does not exist, creating it from template")
|
||||
self.creat_config()
|
||||
|
||||
@@ -1,30 +1,51 @@
|
||||
import logging
|
||||
from discord.ext import commands
|
||||
import asyncio
|
||||
|
||||
LOGGER = logging.getLogger("Discord_Radio_Bot.LinkCop")
|
||||
|
||||
|
||||
class ClearMessages(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.Bot = bot
|
||||
|
||||
@commands.command()
|
||||
async def clear(self, ctx, amount=0):
|
||||
if amount == 0:
|
||||
fail = await ctx.send("Please enter an amount to delete!")
|
||||
await asyncio.sleep(6)
|
||||
await fail.delete()
|
||||
@commands.command(name='clear',
|
||||
help="Use this command to clear a given number of messages from the channel it is called in.\n"
|
||||
"There is a limit of 100 messages. Please be patient, it may take a while to process a large request."
|
||||
"Example command:\n"
|
||||
"\t@ clear\n"
|
||||
"\t@ clear 10",
|
||||
breif="Clear x messages in the channel it's called in")
|
||||
async def clear(self, ctx, amount=2):
|
||||
member = ctx.author.display_name
|
||||
member_id = ctx.author.id
|
||||
mtn_member = f"<@{member_id}>"
|
||||
|
||||
if amount < 3:
|
||||
await ctx.channel.purge(limit=amount)
|
||||
sucess = await ctx.send(
|
||||
f"{amount} messages has been deleted <a:Verified:878231325469974599>") # sending success msg
|
||||
await asyncio.sleep(6) # wait 6 seconds
|
||||
await sucess.delete() # deleting the success msg
|
||||
if isinstance(amount, int):
|
||||
if not amount > 0:
|
||||
ctx.channel.send(f"{member}, the number needs to be positive...")
|
||||
|
||||
else:
|
||||
LOGGER.info(f"Clear {amount} messages requested by {member}")
|
||||
|
||||
authors = {}
|
||||
async for message in ctx.channel.history(limit=amount):
|
||||
if message.author not in authors:
|
||||
authors[message.author] = 1
|
||||
else:
|
||||
authors[message.author] += 1
|
||||
await message.delete()
|
||||
|
||||
msg = f"{mtn_member}, I deleted {sum(authors.values())} messages from {len(authors.keys())} users:\n"
|
||||
LOGGER.debug(f"Deleted {sum(authors.values())} messages from {ctx.message.channel}")
|
||||
|
||||
for author in authors.keys():
|
||||
msg += f"\t{str(author).split('#', 1)[0]}: {authors[author]}\n"
|
||||
LOGGER.debug(f"Deleted {authors[author]} messages from {author}")
|
||||
|
||||
await ctx.channel.send(msg)
|
||||
|
||||
else:
|
||||
if amount == 0:
|
||||
fail = await ctx.send("Please enter an amount to delete!")
|
||||
await asyncio.sleep(6)
|
||||
await fail.delete()
|
||||
ctx.channel.send(f"{member}, you should check out the 'help' section...")
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
|
||||
@@ -3,6 +3,7 @@ import shutil
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
from BotResources import DEFAULT_RADIO_SETTINGS
|
||||
|
||||
|
||||
class OP25Handler(threading.Thread):
|
||||
@@ -12,7 +13,7 @@ class OP25Handler(threading.Thread):
|
||||
self.OP25EXE: str = shutil.which("/home/pi/op25/op25/gr-op25_repeater/apps/rx.py")
|
||||
self.OP25Proc = None
|
||||
|
||||
self.Frequency = None
|
||||
self.Frequency = DEFAULT_RADIO_SETTINGS['freq']
|
||||
|
||||
self.HTTP_ENABLED = False
|
||||
|
||||
@@ -70,7 +71,8 @@ class OP25Handler(threading.Thread):
|
||||
|
||||
self.logger.debug(f"OP25 Keyword Args: {p25_kwargs}")
|
||||
|
||||
self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=False, cwd=self.OP25Dir)
|
||||
self.OP25Proc = subprocess.Popen(p25_kwargs, executable=self.OP25EXE, shell=False, cwd=self.OP25Dir,
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
||||
|
||||
def close_op25(self):
|
||||
self.logger.info(f"Closing OP25")
|
||||
@@ -81,7 +83,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")
|
||||
|
||||
0
templates/__init__.py
Normal file
0
templates/__init__.py
Normal file
41
templates/gqrx_config_template.py
Normal file
41
templates/gqrx_config_template.py
Normal file
@@ -0,0 +1,41 @@
|
||||
drb_defaults = """[General]
|
||||
configversion=2
|
||||
crashed=false
|
||||
|
||||
[audio]
|
||||
gain=-20
|
||||
udp_host=localhost
|
||||
|
||||
[dxcluster]
|
||||
DXCAddress=localhost
|
||||
DXCFilter=
|
||||
DXCPort=7300
|
||||
DXCSpotTimeout=10
|
||||
DXCUsername=nocall
|
||||
|
||||
[fft]
|
||||
averaging=85
|
||||
fft_window=5
|
||||
waterfall_span=1
|
||||
|
||||
[gui]
|
||||
geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x4t\0\0\0$\0\0\a\x7f\0\0\x3\x12\0\0\x4v\0\0\0\x42\0\0\a\x7f\0\0\x3\x12\0\0\0\0\0\0\0\0\a\x80\0\0\x4v\0\0\0\x42\0\0\a\x7f\0\0\x3\x12)
|
||||
state=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x2\0\0\0\x1\0\0\x1G\0\0\x2t\xfc\x2\0\0\0\x2\xfc\0\0\0\x42\0\0\x1\x89\0\0\x1\x89\0\b\0!\xfa\0\0\0\x1\x2\0\0\0\x3\xfb\0\0\0\x18\0\x44\0o\0\x63\0k\0I\0n\0p\0u\0t\0\x43\0t\0l\x1\0\0\0\0\xff\xff\xff\xff\0\0\x1P\0\xff\xff\xff\xfb\0\0\0\x12\0\x44\0o\0\x63\0k\0R\0x\0O\0p\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\x1g\0\a\xff\xff\xfb\0\0\0\xe\0\x44\0o\0\x63\0k\0\x46\0\x66\0t\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xc8\0\a\xff\xff\xfc\0\0\x1\xd1\0\0\0\xe5\0\0\0\xc3\0\xff\xff\xff\xfa\0\0\0\0\x2\0\0\0\x2\xfb\0\0\0\x12\0\x44\0o\0\x63\0k\0\x41\0u\0\x64\0i\0o\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\xc3\0\xff\xff\xff\xfb\0\0\0\xe\0\x44\0o\0\x63\0k\0R\0\x44\0S\0\0\0\0\0\xff\xff\xff\xff\0\0\0h\0\xff\xff\xff\0\0\0\x3\0\0\0\0\0\0\0\0\xfc\x1\0\0\0\x1\xfb\0\0\0\x1a\0\x44\0o\0\x63\0k\0\x42\0o\0o\0k\0m\0\x61\0r\0k\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\x1\x42\0\xff\xff\xff\0\0\x1\xbd\0\0\x2t\0\0\0\x1\0\0\0\x2\0\0\0\b\0\0\0\x2\xfc\0\0\0\x1\0\0\0\x2\0\0\0\x1\0\0\0\x16\0m\0\x61\0i\0n\0T\0o\0o\0l\0\x42\0\x61\0r\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)
|
||||
|
||||
[input]
|
||||
dc_cancel=true
|
||||
device="rtl=0"
|
||||
frequency=154785000
|
||||
gains=@Variant(\0\0\0\b\0\0\0\x1\0\0\0\x6\0L\0N\0\x41\0\0\0\x2\0\0\x1P)
|
||||
sample_rate=1800000
|
||||
|
||||
[receiver]
|
||||
demod=3
|
||||
filter_high_cut=2500
|
||||
filter_low_cut=-2500
|
||||
offset=-590400
|
||||
sql_level=-50
|
||||
|
||||
[remote_control]
|
||||
allowed_hosts=localhost, 127.0.0.1, ::1
|
||||
enabled=true"""
|
||||
Reference in New Issue
Block a user