import { DebugBuilder } from "../../modules/debugger.mjs"; const log = new DebugBuilder("client", "op25ConfigGenerator"); import { promises as fs } from 'fs'; class OP25ConfigObject { constructor() { } async exportToFile(filename) { try { const jsonConfig = JSON.stringify(this, null, 2); await fs.writeFile(filename, jsonConfig); log.INFO(`Config exported to ${filename}`); } catch (error) { log.ERROR(`Error exporting config to ${filename}: ${error}`); } } } export class P25ConfigGenerator extends OP25ConfigObject { constructor({ systemName, controlChannels, tagsFile, whitelistFile = undefined }) { super(); log.INFO("Generating P25 Config for:", systemName); const controlChannelsString = controlChannels.join(','); this.channels = [new channelConfig({ "channelName": systemName, "systemName": systemName, "enableAnalog": "off", "demodType": "cqpsk", "cqpskTracking": true, "filterType": "rc" })]; this.devices = [new deviceConfig({ "gain": "LNA:36" })]; this.trunking = new trunkingConfig({ "module": "tk_p25.py", "systemName": systemName, "controlChannelsString": controlChannelsString, "tagsFile": tagsFile, "whitelist": whitelistFile }); this.audio = new audioConfig({}); this.terminal = new terminalConfig({}); } } export class NBFMConfigGenerator extends OP25ConfigObject { constructor({ systemName, frequency, nbfmSquelch = -70 }) { super(); this.channels = new channelConfig({ "channelName": systemName, "enableAnalog": "on", "nbfmSquelch": nbfmSquelch, "frequency": frequency, "demodType": "fsk4", "filterType": "widepulse" }); this.devices = new deviceConfig({ "gain": "LNA:32" }); this.audio = new audioConfig({}); this.terminal = new terminalConfig({}); } } class channelConfig { constructor({ channelName = "Voice_ch1", device = "sdr0", systemName, metaStreamName, demodType, // cqpsk: P25; fsk4: everything else cqpskTracking, trackingThreshold = 120, trackingFeedback = 0.75, destination = "udp://127.0.0.1:23456", excess_bw = 0.2, filterType = "rc", // rc: P25; widepulse: analog ifRate = 24000, plot = "", symbolRate = 4800, enableAnalog, //[on, off, auto] nbfmDeviation = 4000, // only needed if analog is enabled nbfmSquelch = -50, // only needed if analog is enabled frequency, // only needed if analog is enabled blacklist, whitelist, cryptKeys }) { // Core Configs this.name = channelName; this.device = device; this.demod_type = demodType; this.destination = destination; this.excess_bw = excess_bw; this.filter_type = filterType; this.if_rate = ifRate; this.plot = plot; this.symbol_rate = symbolRate; this.enable_analog = enableAnalog; // P25 config if (!enableAnalog || enableAnalog === "off" || systemName) this.trunking_sysname = systemName; if (!enableAnalog || enableAnalog === "off" || systemName && metaStreamName) this.meta_stream_name = metaStreamName ?? ""; if (!enableAnalog || enableAnalog === "off" || systemName) this.cqpsk_tracking = cqpskTracking; if (!enableAnalog || enableAnalog === "off" || systemName) this.tracking_threshold = trackingThreshold; if (!enableAnalog || enableAnalog === "off" || systemName) this.tracking_feedback = trackingFeedback; if (!enableAnalog || enableAnalog === "off" || systemName && blacklist) this.blacklist = blacklist ?? ""; if (!enableAnalog || enableAnalog === "off" || systemName && whitelist) this.whitelist = whitelist ?? ""; if (!enableAnalog || enableAnalog === "off" || systemName && cryptKeys) this.crypt_keys = cryptKeys ?? ""; // Analog config if (enableAnalog === "on" || enableAnalog === "auto") this.nbfm_deviation = nbfmDeviation; if (enableAnalog === "on" || enableAnalog === "auto") this.nbfm_squelch = nbfmSquelch; if (enableAnalog === "on" || enableAnalog === "auto") this.frequency = frequency; } } class deviceConfig { constructor({ args = "rtl", gain = "LNA:32", gainMode = false, name = "sdr0", offset = 0, ppm = 0.0, sampleRate = 1920000, tunable = true }) { this.args = args this.gains = gain this.gain_mode = gainMode this.name = name this.offset = offset this.ppm = ppm this.rate = sampleRate this.usable_bw_pct = 0.85 this.tunable = tunable } } class trunkingConfig { /** * * @param {object} * */ constructor({ module, systemName, controlChannelsString, tagsFile = "", nac = "0x0", wacn = "0x0", cryptBehavior = 2, whitelist = "", blacklist = "" }) { this.module = module; this.chans = [{ "nac": nac, "wacn": wacn, "sysname": systemName, "control_channel_list": controlChannelsString, "whitelist": whitelist, "blacklist": blacklist, "tgid_tags_file": tagsFile, "tdma_cc": false, "crypt_behavior": cryptBehavior }]; } } class audioConfig { constructor({ module = "sockaudio.py", port = 23456, deviceName = "default" }) { this.module = module; this.instances = [{ "instance_name": "audio0", "device_name": deviceName, "udp_port": port, "audio_gain": 2.0, "number_channels": 1 }]; } } class metadataStreamConfig { constructor({ }) { this.module = ""; this.streams = []; } } class terminalConfig { constructor({ module = "terminal.py", terminalType = "http:0.0.0.0:8081" }) { this.module = module; this.terminal_type = terminalType; this.curses_plot_interval = 0.1; this.http_plot_interval = 1.0; this.http_plot_directory = "../www/images"; this.tuning_step_large = 1200; this.tuning_step_small = 100; } }