Finalizing #9
- Added service handler for system services - Control OP25 from service handler - Generate and save OP25 config file - Handlers for OP25
This commit is contained in:
52
client/modules/serviceHandler.mjs
Normal file
52
client/modules/serviceHandler.mjs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { exec } from 'child_process';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the given service from the command line.
|
||||||
|
* @param {string} serviceName The service name to be started. Ex: ... start "{serviceName}.service"
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export const startService = async (serviceName) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(`sudo systemctl start ${serviceName}.service`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restarts the given service from the command line.
|
||||||
|
* @param {string} serviceName The service name to be restarted. Ex: ... restart "{serviceName}.service"
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export const restartService = async (serviceName) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(`sudo systemctl restart ${serviceName}.service`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the given service from the command line.
|
||||||
|
* @param {string} serviceName The service name to be stopped. Ex: ... stop "{serviceName}.service"
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export const stopService = async (serviceName) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
exec(`sudo systemctl stop ${serviceName}.service`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -17,18 +17,19 @@ class OP25ConfigObject {
|
|||||||
export class P25ConfigGenerator extends OP25ConfigObject {
|
export class P25ConfigGenerator extends OP25ConfigObject {
|
||||||
constructor({ systemName, controlChannels, tagsFile, whitelistFile = undefined }) {
|
constructor({ systemName, controlChannels, tagsFile, whitelistFile = undefined }) {
|
||||||
super();
|
super();
|
||||||
|
console.log("Generating P25 Config for:", systemName);
|
||||||
const controlChannelsString = controlChannels.join(',');
|
const controlChannelsString = controlChannels.join(',');
|
||||||
this.channels = new channelConfig({
|
this.channels = [new channelConfig({
|
||||||
"channelName": systemName,
|
"channelName": systemName,
|
||||||
"systemName": systemName,
|
"systemName": systemName,
|
||||||
"enableAnalog": "off",
|
"enableAnalog": "off",
|
||||||
"demodType": "cqpsk",
|
"demodType": "cqpsk",
|
||||||
"cqpskTracking": true,
|
"cqpskTracking": true,
|
||||||
"filterType": "rc"
|
"filterType": "rc"
|
||||||
});
|
})];
|
||||||
this.devices = new deviceConfig({
|
this.devices = [new deviceConfig({
|
||||||
"gain": "LNA:36"
|
"gain": "LNA:36"
|
||||||
});
|
})];
|
||||||
this.trunking = new trunkingConfig({
|
this.trunking = new trunkingConfig({
|
||||||
"module": "tk_p25.py",
|
"module": "tk_p25.py",
|
||||||
"systemName": systemName,
|
"systemName": systemName,
|
||||||
@@ -149,7 +150,7 @@ class trunkingConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class audioConfig {
|
class audioConfig {
|
||||||
constructor({ module = "sockaudio.py", port = 23456, deviceName = "default" }) {
|
constructor({ module = "sockaudio.py", port = 23457, deviceName = "default" }) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.instances = [{
|
this.instances = [{
|
||||||
"instance_name": "audio0",
|
"instance_name": "audio0",
|
||||||
@@ -169,7 +170,7 @@ class metadataStreamConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class terminalConfig {
|
class terminalConfig {
|
||||||
constructor({ module = "terminal.py", terminalType = "http:0.0.0.0:8080" }) {
|
constructor({ module = "terminal.py", terminalType = "http:0.0.0.0:8081" }) {
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.terminal_type = terminalType;
|
this.terminal_type = terminalType;
|
||||||
this.curses_plot_interval = 0.1;
|
this.curses_plot_interval = 0.1;
|
||||||
|
|||||||
@@ -1,14 +1,84 @@
|
|||||||
|
import { P25ConfigGenerator, NBFMConfigGenerator } from './modules/op25ConfigGenerators.mjs';
|
||||||
|
import { getAllPresets } from '../modules/radioPresetHandler.mjs';
|
||||||
|
import { startService, stopService } from '../modules/serviceHandler.mjs';
|
||||||
|
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
dotenv.config()
|
||||||
|
|
||||||
let currentSystem = undefined;
|
let currentSystem = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates configuration based on the preset and restarts the OP25 service.
|
||||||
|
* @param {Object} preset The preset object containing system configuration.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const createConfigAndRestartService = async (systemName, preset) => {
|
||||||
|
const { mode, frequencies, trunkFile, whitelistFile } = preset;
|
||||||
|
|
||||||
|
let generator;
|
||||||
|
if (mode === 'p25') {
|
||||||
|
console.log("Using P25 Config Generator based on preset mode", systemName, mode);
|
||||||
|
generator = new P25ConfigGenerator({
|
||||||
|
systemName,
|
||||||
|
controlChannels: frequencies,
|
||||||
|
tagsFile: trunkFile,
|
||||||
|
whitelistFile: whitelistFile !== 'none' ? whitelistFile : undefined
|
||||||
|
});
|
||||||
|
} else if (mode === 'nbfm') {
|
||||||
|
console.log("Using NBFM Config Generator based on preset mode", systemName, mode);
|
||||||
|
generator = new NBFMConfigGenerator({
|
||||||
|
systemName,
|
||||||
|
frequencies,
|
||||||
|
tagsFile: trunkFile
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported mode: ${mode}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const op25FilePath = process.env.OP25_FULL_PATH || './'; // Default to current directory if OP25_FULL_PATH is not set
|
||||||
|
const op25ConfigPath = `${op25FilePath}${op25FilePath.endsWith('/') ? 'active.cfg.json' : '/active.cfg.json'}`;
|
||||||
|
await generator.exportToFile(op25ConfigPath);
|
||||||
|
|
||||||
|
// Restart the service
|
||||||
|
await stopService('op25');
|
||||||
|
await startService('op25');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the OP25 service for the specified system.
|
||||||
|
* @param {string} systemName The name of the system to open.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
export const openOP25 = async (systemName) => {
|
export const openOP25 = async (systemName) => {
|
||||||
currentSystem = systemName;
|
currentSystem = systemName;
|
||||||
}
|
|
||||||
|
|
||||||
|
// Retrieve preset for the specified system name
|
||||||
|
const presets = await getAllPresets();
|
||||||
|
const preset = presets[systemName];
|
||||||
|
|
||||||
|
console.log("Found preset:", preset);
|
||||||
|
|
||||||
|
if (!preset) {
|
||||||
|
throw new Error(`Preset for system "${systemName}" not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await createConfigAndRestartService(systemName, preset);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the OP25 service.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
export const closeOP25 = async () => {
|
export const closeOP25 = async () => {
|
||||||
currentSystem = undefined;
|
currentSystem = undefined;
|
||||||
}
|
await stopService('op25');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current system.
|
||||||
|
* @returns {Promise<string | undefined>} The name of the current system.
|
||||||
|
*/
|
||||||
export const getCurrentSystem = async () => {
|
export const getCurrentSystem = async () => {
|
||||||
return currentSystem;
|
return currentSystem;
|
||||||
}
|
};
|
||||||
Reference in New Issue
Block a user