Major updates to core
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { networkInterfaces } from 'os';
|
||||
import { createHash, randomBytes } from 'crypto';
|
||||
import { promises, constants } from 'fs';
|
||||
import { dirname } from "path";
|
||||
|
||||
/**
|
||||
* Check to see if the input is a valid JSON string
|
||||
@@ -7,7 +9,7 @@ import { createHash, randomBytes } from 'crypto';
|
||||
* @param {*} str The string to check for valud JSON
|
||||
* @returns {true|false}
|
||||
*/
|
||||
export function isJsonString (str) {
|
||||
export const isJsonString = (str) => {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
} catch (e) {
|
||||
@@ -16,12 +18,25 @@ export function isJsonString (str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a path exists, creating it if it does not
|
||||
* @returns {undefined}
|
||||
*/
|
||||
export const ensureDirectoryExists = async (filePath) => {
|
||||
const directory = dirname(filePath);
|
||||
try {
|
||||
await promises.access(directory, constants.F_OK);
|
||||
} catch (error) {
|
||||
await promises.mkdir(directory, { recursive: true });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate a unique ID for a given device, this will also be unique on the same device at a different time.
|
||||
* @returns {string} A generated unique ID
|
||||
*/
|
||||
export function generateUniqueID () {
|
||||
export const generateUniqueID = () => {
|
||||
const netInterfaces = networkInterfaces();
|
||||
let macAddress = '';
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { getAllPresets } from "./radioPresetHandler.mjs";
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config()
|
||||
|
||||
@@ -7,33 +9,43 @@ dotenv.config()
|
||||
export class ClientNodeObject {
|
||||
/**
|
||||
*
|
||||
* @param {string} param0._id The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._nuid The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._name The name of the node (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._nearbySystems An object array of nearby systems (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._capabilities The capabilities of this node (Assigned by the user, and determined by the hardware)
|
||||
*/
|
||||
constructor({ _id = undefined, _name = undefined, _location = undefined, _nearbySystems = undefined}) {
|
||||
this.id = _id;
|
||||
constructor({ _nuid = undefined, _name = undefined, _location = undefined, _capabilities = undefined }) {
|
||||
this.nuid = _nuid;
|
||||
this.name = _name;
|
||||
this.location = _location;
|
||||
this.nearbySystems = _nearbySystems;
|
||||
this.location = _location;
|
||||
this.capabilities = _capabilities
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** The configuration object for the node */
|
||||
export class ClientNodeConfig {
|
||||
/**
|
||||
*
|
||||
* @param {string} param0._nuid The ID of the node (Assigned by the client on first boot)
|
||||
* @param {string} param0._name The name of the node (Assigned by the user)
|
||||
* @param {string} param0._location The physical location of the node (Assigned by the user)
|
||||
* @param {object} param0._nearbySystems An object array of nearby systems (Assigned by the user)
|
||||
* @param {object} param0._capabilities The capabilities of this node (Assigned by the user, and determined by the hardware)
|
||||
*/
|
||||
constructor({
|
||||
_id = process.env.CLIENT_ID,
|
||||
_name = process.env.CLIENT_NAME,
|
||||
_location = process.env.CLIENT_LOCATION,
|
||||
_nearbySystems = undefined, // TODO - Get the presets when loading the config instead of having to do it after the fact
|
||||
_serverIp = process.env.SERVER_IP,
|
||||
_serverPort = process.env.SERVER_PORT,
|
||||
_nuid = process.env.CLIENT_NUID,
|
||||
_name = process.env.CLIENT_NAME,
|
||||
_location = process.env.CLIENT_LOCATION,
|
||||
_nearbySystems = getAllPresets(),
|
||||
_capabilities = process.env.CLIENT_CAPABILITIES.split(", "),
|
||||
_serverIp = process.env.SERVER_IP,
|
||||
_serverPort = process.env.SERVER_PORT,
|
||||
}) {
|
||||
this.node = new ClientNodeObject({
|
||||
_id:_id, _name:_name, _location:_location, _nearbySystems:_nearbySystems
|
||||
_nuid: _nuid, _name: _name, _location: _location, _capabilities: _capabilities
|
||||
});
|
||||
this.nearbySystems = _nearbySystems;
|
||||
this.serverIp = _serverIp;
|
||||
this.serverPort = _serverPort;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
// Debug
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||
const log = new DebugBuilder("client", "updatePresets");
|
||||
// Modules
|
||||
const fs = require('fs');
|
||||
const path = require("path");
|
||||
const converter = require("convert-units");
|
||||
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
|
||||
*/
|
||||
function writePresets(presets, callback = undefined) {
|
||||
log.DEBUG(`${__dirname}`);
|
||||
fs.writeFile("./config/radioPresets.json", JSON.stringify(presets), (err) => {
|
||||
const writePresets = async (presets, callback = undefined) => {
|
||||
console.log(`${__dirname}`);
|
||||
await ensureDirectoryExists(configFilePath);
|
||||
writeFile(configFilePath, JSON.stringify(presets), (err) => {
|
||||
// Error checking
|
||||
if (err) throw err;
|
||||
log.DEBUG("Write Complete");
|
||||
console.log("Write Complete");
|
||||
if (callback) callback(); else return
|
||||
});
|
||||
}
|
||||
@@ -26,14 +31,14 @@ function writePresets(presets, callback = undefined) {
|
||||
* @param frequenciesArray
|
||||
* @returns {*[]}
|
||||
*/
|
||||
function sanitizeFrequencies(frequenciesArray) {
|
||||
const sanitizeFrequencies = async (frequenciesArray) => {
|
||||
let sanitizedFrequencyArray = [];
|
||||
|
||||
for (const freq of frequenciesArray) {
|
||||
sanitizedFrequencyArray.push(convertFrequencyToHertz(freq));
|
||||
}
|
||||
|
||||
log.DEBUG("Sanitized Frequency Array", sanitizedFrequencyArray);
|
||||
console.log("Sanitized Frequency Array", sanitizedFrequencyArray);
|
||||
return sanitizedFrequencyArray;
|
||||
}
|
||||
|
||||
@@ -42,23 +47,23 @@ function sanitizeFrequencies(frequenciesArray) {
|
||||
* @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")
|
||||
*/
|
||||
function convertFrequencyToHertz(frequency){
|
||||
const convertFrequencyToHertz = async (frequency) => {
|
||||
// check if the passed value is a number
|
||||
if(typeof frequency == 'number' && !isNaN(frequency)){
|
||||
if (typeof frequency == 'number' && !isNaN(frequency)) {
|
||||
if (Number.isInteger(frequency)) {
|
||||
log.DEBUG(`${frequency} is an integer.`);
|
||||
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
|
||||
log.WARN("Frequency hasn't matched filters: ", frequency);
|
||||
console.log("Frequency hasn't matched filters: ", frequency);
|
||||
}
|
||||
else {
|
||||
log.DEBUG(`${frequency} is a float value.`);
|
||||
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 {
|
||||
log.DEBUG(`${frequency} is not a number`);
|
||||
console.log(`${frequency} is not a number`);
|
||||
frequency = convertFrequencyToHertz(parseFloat(frequency));
|
||||
|
||||
return parseInt(frequency)
|
||||
@@ -69,10 +74,10 @@ function convertFrequencyToHertz(frequency){
|
||||
* Gets the saved presets and returns a preset object
|
||||
* @returns {any} The object containing the different systems the bot is near
|
||||
*/
|
||||
function getPresets() {
|
||||
const presetDir = path.resolve("./config/radioPresets.json");
|
||||
log.DEBUG(`Getting presets from directory: '${presetDir}'`);
|
||||
if (fs.existsSync(presetDir)) return JSON.parse(fs.readFileSync(presetDir));
|
||||
export const getAllPresets = () => {
|
||||
const presetDir = resolve(configFilePath);
|
||||
console.log(`Getting presets from directory: '${presetDir}'`);
|
||||
if (existsSync(presetDir)) return JSON.parse(readFileSync(presetDir));
|
||||
else return {};
|
||||
}
|
||||
|
||||
@@ -86,15 +91,15 @@ function getPresets() {
|
||||
* @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]
|
||||
*/
|
||||
function addNewPreset(systemName, frequencies, mode, callback, trunkFile = undefined, whitelistFile = undefined) {
|
||||
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"
|
||||
}
|
||||
"frequencies": sanitizeFrequencies(frequencies),
|
||||
"mode": mode,
|
||||
"trunkFile": trunkFile ?? "none",
|
||||
"whitelistFile": whitelistFile ?? "none"
|
||||
}
|
||||
// Write the changes to the preset config file
|
||||
writePresets(presets, callback);
|
||||
}
|
||||
@@ -109,15 +114,15 @@ function addNewPreset(systemName, frequencies, mode, callback, trunkFile = undef
|
||||
* @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]
|
||||
*/
|
||||
function updatePreset(systemName, callback, { frequencies = undefined, mode = undefined, trunkFile = undefined, whitelistFile = undefined }) {
|
||||
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";
|
||||
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);
|
||||
}
|
||||
@@ -129,14 +134,11 @@ function updatePreset(systemName, callback, { frequencies = undefined, mode = un
|
||||
* @param {string} systemName The name of the system being modified
|
||||
* @param {function} callback The callback function to be called when the function completes
|
||||
*/
|
||||
function removePreset(systemName, callback) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +1,28 @@
|
||||
import { io } from "socket.io-client";
|
||||
import { connectToChannel, initDiscordBotClient, getVoiceChannelFromID } from '../discordAudioBot/dab.mjs';
|
||||
import { logIntoServerWrapper, sendNodeUpdateWrapper } from "./socketClientWrappers.mjs";
|
||||
|
||||
export function initSocketConnection(localNodeConfig) {
|
||||
export const initSocketConnection = async (localNodeConfig) => {
|
||||
const serverEndpoint = `http://${localNodeConfig.serverIp}:${localNodeConfig.serverPort}` || 'http://localhost:3000'; // Adjust the server endpoint
|
||||
|
||||
const socket = io.connect(serverEndpoint);
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
export function initSocketListeners(socket, localNodeConfig) {
|
||||
socket.on('connect', () => {
|
||||
socket.on('connect', async () => {
|
||||
console.log('Connected to the server');
|
||||
logIntoServer(socket, localNodeConfig.node);
|
||||
await logIntoServerWrapper(socket, localNodeConfig);
|
||||
});
|
||||
|
||||
socket.on('node-join', async (joinData) => {
|
||||
console.log("Join requested: ", joinData)
|
||||
// TODO - Implement logic to control OP25 for the requested channel
|
||||
// TODO - Implement logic to control OP25 for the requested channel/system
|
||||
|
||||
// Join the requested channel with the requested ID
|
||||
initDiscordBotClient(joinData.clientID, client => {
|
||||
console.log("Client:", client);
|
||||
initDiscordBotClient(joinData.clientID, client => {
|
||||
getVoiceChannelFromID(client, joinData.channelID).then(vc => {
|
||||
console.log("Voice Channel:", vc);
|
||||
console.log("Voice Channel Guild:", vc.Guild);
|
||||
const connection = connectToChannel(vc);
|
||||
console.log("Bot Connected to VC");
|
||||
})
|
||||
});
|
||||
console.log("All done?");
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('node-leave', () => {
|
||||
@@ -39,12 +33,5 @@ export function initSocketListeners(socket, localNodeConfig) {
|
||||
console.log('Disconnected from the server');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function logIntoServer(socket, nodeData) {
|
||||
socket.emit("node-login", nodeData);
|
||||
}
|
||||
|
||||
export function sendNodeUpdate(socket, nodeData) {
|
||||
socket.emit('node-update', nodeData);
|
||||
return socket;
|
||||
}
|
||||
11
client/modules/socketClientWrappers.mjs
Normal file
11
client/modules/socketClientWrappers.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
export const logIntoServerWrapper = async (socket, localNodeConfig) => {
|
||||
socket.emit("node-login", localNodeConfig.node);
|
||||
sendNodeUpdateWrapper(socket, localNodeConfig);
|
||||
}
|
||||
|
||||
export const sendNodeUpdateWrapper = async (socket, localNodeConfig) => {
|
||||
socket.emit('node-update', {
|
||||
'node': localNodeConfig.node,
|
||||
'nearbySystems': localNodeConfig.nearbySystems
|
||||
});
|
||||
}
|
||||
@@ -17,8 +17,8 @@ class Options {
|
||||
* @param updatedId The updated ID assigned to the node
|
||||
*/
|
||||
export function updateId (updatedId) {
|
||||
updateConfig('CLIENT_ID', updatedId);
|
||||
process.env.CLIENT_ID = updatedId;
|
||||
updateConfig('CLIENT_NUID', updatedId);
|
||||
process.env.CLIENT_NUID = updatedId;
|
||||
console.log("Updated ID to: ", updatedId);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export function updateClientConfig (runningConfig, newConfigObject) {
|
||||
if (configKeys.includes("id")) {
|
||||
if (runningConfig.id != newConfigObject.id) {
|
||||
this.updateId(newConfigObject.id);
|
||||
updatedKeys.push({ 'CLIENT_ID': newConfigObject.id });
|
||||
updatedKeys.push({ 'CLIENT_NUID': newConfigObject.id });
|
||||
}
|
||||
}
|
||||
if (configKeys.includes("name")) {
|
||||
|
||||
Reference in New Issue
Block a user