// Modules import { writeFile, existsSync, readFileSync } from 'fs'; import { resolve } from "path"; import { ensureDirectoryExists } from "./baseUtils.mjs"; import convert_units from "convert-units"; const { converter } = convert_units; import dotenv from 'dotenv'; dotenv.config() const configFilePath = process.env.CONFIG_PATH; /** * Write the given presets to the JSON file * @param presets The preset or presets to be written * @param {function} callback The function to be called when this wrapper completes */ const writePresets = async (presets, callback = undefined) => { console.log(`${__dirname}`); await ensureDirectoryExists(configFilePath); writeFile(configFilePath, JSON.stringify(presets), (err) => { // Error checking if (err) throw err; console.log("Write Complete"); if (callback) callback(); else return }); } /** * Wrapper to ensure each value in the array is in Hz format * @param frequenciesArray * @returns {*[]} */ const sanitizeFrequencies = async (frequenciesArray) => { let sanitizedFrequencyArray = []; for (const freq of frequenciesArray) { sanitizedFrequencyArray.push(convertFrequencyToHertz(freq)); } console.log("Sanitized Frequency Array", sanitizedFrequencyArray); return sanitizedFrequencyArray; } /** * Function to convert a string or a float into the integer type needed to be saved * @param frequency Could be a string, number or float, * @returns {number|number|*} Return the value to be saved in Hz format ("154.875"MHz format = "154875000") */ const convertFrequencyToHertz = async (frequency) => { // check if the passed value is a number if (typeof frequency == 'number' && !isNaN(frequency)) { if (Number.isInteger(frequency)) { console.log(`${frequency} is an integer.`); // Check to see if the frequency has the correct length if (frequency >= 1000000) return frequency if (frequency >= 100 && frequency <= 999) return frequency * 1000000 console.log("Frequency hasn't matched filters: ", frequency); } else { console.log(`${frequency} is a float value.`); // Convert to a string to remove the decimal in place and then correct the length return parseInt(converter(frequency).from("MHz").to("Hz")); } } else { console.log(`${frequency} is not a number`); frequency = convertFrequencyToHertz(parseFloat(frequency)); return parseInt(frequency) } } /** * Gets the saved presets and returns a preset object * @returns {any} The object containing the different systems the bot is near */ export const getAllPresets = () => { const presetDir = resolve(configFilePath); console.log(`Getting presets from directory: '${presetDir}'`); if (existsSync(presetDir)) return JSON.parse(readFileSync(presetDir)); else return {}; } /** * Adds a new preset to the radioPresets JSON file * * @param {string} systemName The name of the system being added * @param {Array} frequencies The frequency or frequencies the SDR should tune to for this system * @param {string} mode The listening mode the SDR should be using when listening to this frequency * @param {function} callback The callback function to call when completed * @param {string} trunkFile The file that contains all trunking information (if applicable to the selected listening mode) * @param {string} whitelistFile The file that contains the whitelisted talkgroups [optional] */ export const addNewPreset = (systemName, frequencies, mode, callback, trunkFile = undefined, whitelistFile = undefined) => { const presets = this.getPresets(); // Create the preset for the new system presets[systemName] = { "frequencies": sanitizeFrequencies(frequencies), "mode": mode, "trunkFile": trunkFile ?? "none", "whitelistFile": whitelistFile ?? "none" } // Write the changes to the preset config file writePresets(presets, callback); } /** * Updates the specified system * * @param {string} systemName The name of the system being modified * @param {function} callback The callback function to be called when the function completes * @param {Array} frequencies The frequency or frequencies the SDR should tune to for this system * @param {string} mode The listening mode the SDR should be using when listening to this frequency * @param {string} trunkFile The file that contains all trunking information (if applicable to the selected listening mode) * @param {string} whitelistFile The file that contains the whitelisted talkgroups [optional] */ export const updatePreset = (systemName, callback, { frequencies = undefined, mode = undefined, trunkFile = undefined, whitelistFile = undefined }) => { const presets = this.getPresets(); // Check if a system name was passed if (systemName in presets) { // System name exists, checking to see if the keys are different if (frequencies && sanitizeFrequencies(frequencies) !== presets[systemName].frequencies) presets[systemName].frequencies = sanitizeFrequencies(frequencies); if (mode && mode !== presets[systemName].mode) presets[systemName].mode = mode; if (trunkFile && trunkFile !== presets[systemName].trunkFile || trunkFile === "") presets[systemName].trunkFile = trunkFile ?? "none"; if (whitelistFile && whitelistFile !== presets[systemName].whitelistFile || whitelistFile === "") presets[systemName].whitelistFile = whitelistFile ?? "none"; // Write the changes writePresets(presets, callback); } } /** * Deletes the specified system * * @param {string} systemName The name of the system being modified * @param {function} callback The callback function to be called when the function completes */ export const removePreset = (systemName, callback) => { const presets = this.getPresets(); // Check if a system name was passed if (systemName in presets) { delete presets[systemName]; writePresets(presets, callback); } }