Merge pull request 'Correctly implement actions' (#3) from implement-actions into master
Some checks failed
Lint / lint (push) Successful in 12s
release-tag / release-image (push) Failing after 19m3s

Reviewed-on: #3
This commit is contained in:
2025-02-23 11:31:30 -05:00
8 changed files with 36 additions and 65 deletions

View File

@@ -3,7 +3,7 @@ name: release-tag
on: on:
push: push:
branches: branches:
- main - master
jobs: jobs:
release-image: release-image:

View File

@@ -3,22 +3,22 @@ name: Lint
on: on:
push: push:
branches: branches:
- main - master
pull_request: pull_request:
branches: branches:
- main - "*"
jobs: jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v5
with: with:
python-version: 3.x python-version: '3.13'
- name: Install dependencies - name: Install dependencies
run: | run: |

View File

@@ -1,30 +0,0 @@
name: Test
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
- name: Run tests
run: |
pytest

View File

@@ -30,15 +30,15 @@ class AudioStream:
if _input: if _input:
self.paInstance_kwargs['input_device_index'] = _input_device_index self.paInstance_kwargs['input_device_index'] = _input_device_index
else: else:
LOGGER.warning(f"[AudioStream.__init__]:\tInput was not enabled." LOGGER.warning("[AudioStream.__init__]:\tInput was not enabled."
f" Reinitialize with '_input=True'") " Reinitialize with '_input=True'")
if _output_device_index: if _output_device_index:
if _output: if _output:
self.paInstance_kwargs['output_device_index'] = _output_device_index self.paInstance_kwargs['output_device_index'] = _output_device_index
else: else:
LOGGER.warning(f"[AudioStream.__init__]:\tOutput was not enabled." LOGGER.warning("[AudioStream.__init__]:\tOutput was not enabled."
f" Reinitialize with '_output=True'") " Reinitialize with '_output=True'")
if _init_on_startup: if _init_on_startup:
# Init PyAudio instance # Init PyAudio instance
@@ -59,15 +59,15 @@ class AudioStream:
if self.paInstance_kwargs['input']: if self.paInstance_kwargs['input']:
self.paInstance_kwargs['input_device_index'] = _new_input_device_index self.paInstance_kwargs['input_device_index'] = _new_input_device_index
else: else:
LOGGER.warning(f"[AudioStream.init_stream]:\tInput was not enabled when initialized." LOGGER.warning("[AudioStream.init_stream]:\tInput was not enabled when initialized."
f" Reinitialize with '_input=True'") " Reinitialize with '_input=True'")
if _new_output_device_index: if _new_output_device_index:
if self.paInstance_kwargs['output']: if self.paInstance_kwargs['output']:
self.paInstance_kwargs['output_device_index'] = _new_output_device_index self.paInstance_kwargs['output_device_index'] = _new_output_device_index
else: else:
LOGGER.warning(f"[AudioStream.init_stream]:\tOutput was not enabled when initialized." LOGGER.warning("[AudioStream.init_stream]:\tOutput was not enabled when initialized."
f" Reinitialize with '_output=True'") " Reinitialize with '_output=True'")
self.close_if_open() self.close_if_open()
@@ -80,7 +80,7 @@ class AudioStream:
if self.stream.is_active(): if self.stream.is_active():
self.stream.stop_stream() self.stream.stop_stream()
self.stream.close() self.stream.close()
LOGGER.debug(f"[ReopenStream.close_if_open]:\t Stream was open; It was closed.") LOGGER.debug("[ReopenStream.close_if_open]:\t Stream was open; It was closed.")
def list_devices(self, _display_input_devices: bool = True, _display_output_devices: bool = True): def list_devices(self, _display_input_devices: bool = True, _display_output_devices: bool = True):
LOGGER.info('Getting a list of the devices connected') LOGGER.info('Getting a list of the devices connected')
@@ -126,7 +126,7 @@ class NoiseGate(AudioStream):
def run(self) -> None: def run(self) -> None:
global voice_connection global voice_connection
# Start the audio stream # Start the audio stream
LOGGER.debug(f"Starting stream") LOGGER.debug("Starting stream")
self.stream.start_stream() self.stream.start_stream()
# Start the stream to discord # Start the stream to discord
self.core() self.core()
@@ -139,15 +139,15 @@ class NoiseGate(AudioStream):
time.sleep(.2) time.sleep(.2)
if not voice_connection.is_playing(): if not voice_connection.is_playing():
LOGGER.debug(f"Playing stream to discord") LOGGER.debug("Playing stream to discord")
voice_connection.play(self.NGStream, after=self.core) voice_connection.play(self.NGStream, after=self.core)
async def close(self): async def close(self):
LOGGER.debug(f"Closing") LOGGER.debug("Closing")
await voice_connection.disconnect() await voice_connection.disconnect()
if self.stream.is_active: if self.stream.is_active:
self.stream.stop_stream() self.stream.stop_stream()
LOGGER.debug(f"Stopping stream") LOGGER.debug("Stopping stream")
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
@@ -155,7 +155,7 @@ class NoiseGateStream(discord.AudioSource):
def __init__(self, _stream): def __init__(self, _stream):
super(NoiseGateStream, self).__init__() super(NoiseGateStream, self).__init__()
self.stream = _stream # The actual audio stream object self.stream = _stream # The actual audio stream object
self.NG_fadeout = 240/20 # Fadeout value used to hold the noisegate after de-triggering self.NG_fadeout = 240 / 20 # Fadeout value used to hold the noisegate after de-triggering
self.NG_fadeout_count = 0 # A count set when the noisegate is triggered and was de-triggered self.NG_fadeout_count = 0 # A count set when the noisegate is triggered and was de-triggered
self.process_set_count = 0 # Counts how many processes have been made self.process_set_count = 0 # Counts how many processes have been made

View File

@@ -88,10 +88,10 @@ class DiscordBotManager:
voice_client = await channel.connect() voice_client = await channel.connect()
streamHandler = NoiseGate( streamHandler = NoiseGate(
_input_device_index=device_id, _input_device_index=device_id,
_voice_connection=voice_client, _voice_connection=voice_client,
_noise_gate_threshold=ng_threshold) _noise_gate_threshold=ng_threshold)
# Start the audio stream # Start the audio stream
streamHandler.run() streamHandler.run()
self.voice_clients[guild_id] = voice_client self.voice_clients[guild_id] = voice_client
print(f"Joined guild {guild_id} voice channel {channel_id}.") print(f"Joined guild {guild_id} voice channel {channel_id}.")
@@ -108,6 +108,7 @@ class DiscordBotManager:
del self.voice_clients[guild_id] del self.voice_clients[guild_id]
print(f"Left guild {guild_id} voice channel.") print(f"Left guild {guild_id} voice channel.")
# Initialize Discord Bot Manager # Initialize Discord Bot Manager
bot_manager = DiscordBotManager() bot_manager = DiscordBotManager()
@@ -154,4 +155,4 @@ async def get_status():
app.include_router(op25_controller.router, prefix="/op25") app.include_router(op25_controller.router, prefix="/op25")
app.include_router(pulse.router, prefix="/pulse") app.include_router(pulse.router, prefix="/pulse")

View File

@@ -8,4 +8,4 @@ for inputDevice in list_of_devices['Input']:
print("----- OUTPUT DEVICES -----") print("----- OUTPUT DEVICES -----")
for outputDevice in list_of_devices['Output']: for outputDevice in list_of_devices['Output']:
print(f"{outputDevice}\t-\t{list_of_devices['Output'][outputDevice]}") print(f"{outputDevice}\t-\t{list_of_devices['Output'][outputDevice]}")

View File

@@ -1,4 +1,4 @@
from fastapi import FastAPI, HTTPException, APIRouter from fastapi import HTTPException, APIRouter
from pydantic import BaseModel from pydantic import BaseModel
from enum import Enum from enum import Enum
import subprocess import subprocess
@@ -6,7 +6,7 @@ import os
import signal import signal
import json import json
import csv import csv
from typing import List, Optional, Union from typing import List, Optional
router = APIRouter() router = APIRouter()
@@ -87,7 +87,7 @@ class ChannelConfig(BaseModel):
symbol_rate: Optional[int] = 4800 symbol_rate: Optional[int] = 4800
blacklist: Optional[str] = "" blacklist: Optional[str] = ""
whitelist: Optional[str] = "" whitelist: Optional[str] = ""
class DeviceConfig(BaseModel): class DeviceConfig(BaseModel):
args: Optional[str] = "rtl" args: Optional[str] = "rtl"
gains: Optional[str] = "lna:39" gains: Optional[str] = "lna:39"
@@ -170,7 +170,7 @@ async def generate_config(generator: ConfigGenerator):
"audio": audio.dict(), "audio": audio.dict(),
"terminal": terminal.dict() "terminal": terminal.dict()
} }
elif generator.type == DecodeMode.ANALOG: elif generator.type == DecodeMode.ANALOG:
generator = generator.config generator = generator.config
channels = [ChannelConfig( channels = [ChannelConfig(
@@ -190,11 +190,11 @@ async def generate_config(generator: ConfigGenerator):
else: else:
raise HTTPException(status_code=400, detail="Invalid configuration type. Must be 'p25' or 'nbfm'.") raise HTTPException(status_code=400, detail="Invalid configuration type. Must be 'p25' or 'nbfm'.")
with open('/configs/active.cfg.json', 'w') as f: with open('/configs/active.cfg.json', 'w') as f:
json.dump(del_none_in_dict(config_dict), f, indent=2) json.dump(del_none_in_dict(config_dict), f, indent=2)
return {"message": f"Config exported to '/configs/active.cfg.json'"} return {"message": "Config exported to '/configs/active.cfg.json'"}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e))
@@ -222,7 +222,7 @@ def save_whitelist(talkgroup_tags: List[int]) -> None:
writer = csv.writer(file, delimiter='\t', lineterminator='\n') writer = csv.writer(file, delimiter='\t', lineterminator='\n')
# Write rows # Write rows
for tag in talkgroup_tags: for tag in talkgroup_tags:
writer.writerow([tag]) writer.writerow([tag])
def del_none_in_dict(d): def del_none_in_dict(d):
""" """
@@ -239,4 +239,4 @@ def del_none_in_dict(d):
elif isinstance(value, list): elif isinstance(value, list):
for iterative_value in value: for iterative_value in value:
del_none_in_dict(iterative_value) del_none_in_dict(iterative_value)
return d # For convenience return d # For convenience

View File

@@ -11,4 +11,4 @@ async def get_status():
return {"status": "running" if pulse_process else "stopped"} return {"status": "running" if pulse_process else "stopped"}
# subprocess.Popen(os.path.join(OP25_PATH, OP25_SCRIPT), shell=True, preexec_fn=os.setsid, cwd=OP25_PATH) # subprocess.Popen(os.path.join(OP25_PATH, OP25_SCRIPT), shell=True, preexec_fn=os.setsid, cwd=OP25_PATH)