Generate new op25.liq each time we change the config + mini fixes
Some checks failed
Lint / lint (push) Failing after 54s
release-tag / release-image (push) Has been cancelled

This commit is contained in:
Logan Cusano
2025-10-23 02:39:22 -04:00
parent f56d044471
commit 1392c8b244
5 changed files with 72 additions and 15 deletions

View File

@@ -0,0 +1,34 @@
import os
from internal.op25.liq_template import liquidsoap_config_template
from models import IcecastConfig
def generate_liquid_script(config: IcecastConfig):
"""
Generates the "*.liq" file that's run by OP25 on startup.
Placeholders in the template must be formatted as ${VARIABLE_NAME}.
Args:
config (dict): A dictionary of key-value pairs for substitution.
Keys should match the variable names in the template (e.g., 'icecast_host').
"""
try:
content = liquidsoap_config_template
# Replace variables
for key, value in config.items():
placeholder = f"${{{key}}}"
# Ensure the value is converted to string for replacement
content = content.replace(placeholder, str(value))
print(f" - Replaced placeholder {placeholder}")
# Write the processed content to the output path
output_path = "/op25/op25/gr-op25_repeater/apps/op25.liq"
with open(output_path, 'w') as f:
f.write(content)
print(f"\nSuccessfully wrote processed configuration to: {output_path}")
except FileNotFoundError:
print(f"Error: Template file not found at {template_path}")
except Exception as e:
print(f"An unexpected error occurred: {e}")

View File

@@ -1,4 +1,4 @@
#!/usr/bin/liquidsoap
liquidsoap_config_template = """#!/usr/bin/liquidsoap
# Example liquidsoap streaming from op25 to icecast
# (c) 2019-2021 gnorbury@bondcar.com, wllmbecks@gmail.com
@@ -10,17 +10,15 @@ set("log.level", 1)
# Make the native sample rate compatible with op25
set("frame.audio.samplerate", 8000)
set("init.allow_root", true)
# ==========================================================
# 📢 ICECAST CONFIGURATION USING ENVIRONMENT VARIABLES
# Use getenv("VAR_NAME", "default_value")
# ==========================================================
ICE_HOST = getenv("ICE_HOST", "ic2.vpn.cusano.net")
ICE_PORT = int_of_string(getenv("ICE_PORT", "8000"))
ICE_MOUNT = getenv("ICE_MOUNT", "mountpoint")
ICE_PASSWORD = getenv("ICE_PASSWORD", "hackme")
ICE_DESCRIPTION = getenv("ICE_DESCRIPTION", "op25")
ICE_GENRE = getenv("ICE_GENRE", "Public Safety")
ICE_HOST = "${icecast_host}"
ICE_PORT = ${icecast_port}
ICE_MOUNT = "${icecast_mountpoint}"
ICE_PASSWORD = "${icecast_password}"
ICE_DESCRIPTION = "${icecast_description}"
ICE_GENRE = "${icecast_genre}"
# ==========================================================
input = mksafe(input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -x 2.5 -s"))
@@ -46,4 +44,5 @@ output.icecast(
mount=ICE_MOUNT,
password=ICE_PASSWORD,
mean(input)
)
)
"""

View File

@@ -17,7 +17,7 @@ def save_talkgroup_tags(talkgroup_tags: List[TalkgroupTag]) -> None:
writer = csv.writer(file, delimiter='\t', lineterminator='\n')
# Write rows
for tag in talkgroup_tags:
writer.writerow([tag.talkgroup, tag.tagDec])
writer.writerow([tag.tagDec, tag.talkgroup])
def save_whitelist(talkgroup_tags: List[int]) -> None:
"""

View File

@@ -17,7 +17,7 @@ class ConfigGenerator(BaseModel):
channels: List[Union[int, str]]
tags: Optional[List[TalkgroupTag]]
whitelist: Optional[List[int]]
icecastConfig: Optional[MetadataStreamConfig]
icecastConfig: Optional[IcecastConfig]
class DemodType(str, Enum):
CQPSK = "cqpsk"
@@ -97,3 +97,15 @@ class TerminalConfig(BaseModel):
http_plot_directory: Optional[str] = "../www/images"
tuning_step_large: Optional[int] = 1200
tuning_step_small: Optional[int] = 100
### ======================================================
# Icecast models
class IcecastConfig:
icecast_host: str
icecast_port: int
icecast_mountpoint: str
icecast_password: str
icecast_description: Optional[str] = "OP25"
icecast_genre: Optional[str] = "Public Safety"

View File

@@ -6,6 +6,7 @@ import json
from models import ConfigGenerator, DecodeMode, ChannelConfig, DeviceConfig, TrunkingConfig, TrunkingChannelConfig, TerminalConfig, MetadataConfig, MetadataStreamConfig
from internal.logger import create_logger
from internal.op25_config_utls import save_talkgroup_tags, save_whitelist, del_none_in_dict, get_current_system_from_config
from internal.liquidsoap_config_utils import generate_liquid_script
LOGGER = create_logger(__name__)
@@ -57,7 +58,7 @@ def create_op25_router():
demod_type="cqpsk",
cqpsk_tracking=True,
filter_type="rc",
meta_stream_name=generator.icecastConfig.stream_name
meta_stream_name="stream_0"
)]
devices = [DeviceConfig()]
save_talkgroup_tags(generator.tags)
@@ -73,9 +74,20 @@ def create_op25_router():
)
metadata = MetadataConfig(
streams=[generator.icecastConfig]
streams=[
MetadataStreamConfig(
stream_name="stream_0",
icecastServerAddress = f"{generator.icecastConfig.icecast_host}:{generator.icecastConfig.icecast_port}",
icecastMountpoint = generator.icecastConfig.icecast_mountpoint,
icecastPass = generator.icecastConfig.icecast_password
)
]
)
# Generate the op25.liq file
generate_liquid_script(generator.icecastConfig)
terminal = TerminalConfig()
config_dict = {