// Debug const { DebugBuilder } = require("../utilities/debugBuilder.js"); const log = new DebugBuilder("client", "radioController"); // Modules const { resolve, dirname } = require('path'); const fs = require('fs'); const radioConfig = require('../config/clientConfig').radioAppConfig; const radioConfigHelper = require("../utilities/radioConfigHelper"); const presetWrappers = require("../utilities/updatePresets"); const spawn = require('child_process').spawn; const converter = require("convert-units"); let radioChildProcess, tempRes, radioConfigPath; /** * Closes the radio executable if it's in one */ exports.closeRadioSession = (req, res) => { if (!radioChildProcess) return res.sendStatus(200) tempRes = res; radioChildProcess.kill(); radioChildProcess = undefined; } /** * Change the current 'cfg.json' file to the preset specified * @param {string} presetName */ exports.changeCurrentConfig = (req, res) => { // Check if the given config is saved log.DEBUG("[/radio/changeCurrentConfig] - Checking if provided preset is in the config"); if (!checkIfPresetExists(req.body.presetName)) return res.status(500).JSON("No preset with given name found in config"); // No preset with the given name is in the config // Check if the current config is the same as the preset given const currentConfig = readOP25Config(); if (currentConfig.channels && currentConfig.channels.name === req.body.presetName) { log.DEBUG("[/radio/changeCurrentConfig] - Current config is the same as the preset given"); return res.sendStatus(202); } // Convert radioPreset to OP25 'cfg.json. file log.DEBUG("[/radio/changeCurrentConfig] - Converting radioPreset to OP25 config"); const updatedConfigObject = convertRadioPresetsToOP25Config(req.body.presetName); // Replace current JSON file with the updated file writeOP25Config(updatedConfigObject, () => { res.sendStatus(200); }) } /** * Open a new OP25 process tuned to the specified system */ exports.openRadioSession = () => { if (radioChildProcess) closeRadioSession(); radioChildProcess = spawn(getRadioBinPath()); } /** * Get the location of the 'multi_rx.py' binary from the config */ function getRadioBinPath(){ return resolve(radioConfig.bin); } /** * Write the given config to the JSON file in OP25 the bin dir * @param config The full config to be written to the file * @param {function} callback The function to be called when this wrapper completes */ function writeOP25Config(config, callback = undefined) { log.DEBUG("Updating OP25 config with: ", config); fs.writeFile(getRadioConfigPath(), JSON.stringify(config), (err) => { // Error checking if (err) { log.ERROR(err); throw err; } log.DEBUG("Write Complete"); if (callback) callback() }); } /** * Get the current config file in use by OP25 * @returns {object|*} The parsed config object currently set in OP25 */ function readOP25Config() { const configPath = getRadioConfigPath(); log.DEBUG(`Reading from config path: '${configPath}'`); return JSON.parse(fs.readFileSync(configPath)); } /** * Get the path of the config for the radio app (OP25) and set the global variable */ function getRadioConfigPath(){ let radioConfigDirPath = dirname(getRadioBinPath()); return resolve(`${radioConfigDirPath}/cfg.json`); } /** * Check to see if the preset name exists in the config * @param {string} presetName The system name as saved in the preset * @returns {true||false} */ function checkIfPresetExists(presetName) { const savedPresets = presetWrappers.getPresets(); if (!Object.keys(savedPresets).includes(presetName)) return false; else return true; } /** * Convert a radioPreset to OP25's cfg.json file */ function convertRadioPresetsToOP25Config(presetName){ const savedPresets = presetWrappers.getPresets(); let frequencyString = ""; for (const frequency of savedPresets[presetName].frequencies){ frequencyString += `${converter(frequency).from("Hz").to("MHz")},` } frequencyString = frequencyString.slice(0, -1); let updatedOP25Config; switch (savedPresets[presetName].mode){ case "p25": updatedOP25Config = new radioConfigHelper.P25({ "systemName": presetName, "controlChannelsString": frequencyString, "tagsFile": savedPresets[presetName].trunkFile }); break; case "nbfm": //code for nbfm here updatedOP25Config = new radioConfigHelper.NBFM({ "frequency": frequencyString, "systemName": presetName }); break; default: throw new Error("Radio mode of selected preset not recognized"); } log.DEBUG(updatedOP25Config); return updatedOP25Config; }