Generate new op25.liq each time we change the config + mini fixes
This commit is contained in:
34
app/internal/liquidsoap_config_utils.py
Normal file
34
app/internal/liquidsoap_config_utils.py
Normal 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}")
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
"""
|
||||
@@ -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:
|
||||
"""
|
||||
|
||||
@@ -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"
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user