const path = require("path");
const { ipcRenderer, shell, clipboard } = require("electron");
const exec = require("child_process").spawn;
const sock = require("./sock.js");
const daemon = require("./daemon.js");
require("./preload-chat.js");
require("./preload-mesh.js");
require("./preload-log.js");
const fs = require("fs");
const FD = require("./freedata");
const {
locatorToLatLng,
distance,
bearingDistance,
latLngToLocator,
} = require("qth-locator");
const { v4: uuidv4 } = require("uuid");
const os = require("os");
// split character used for appending additional data to files
const split_char = "\0;";
// https://stackoverflow.com/a/26227660
var appDataFolder =
process.env.APPDATA ||
(process.platform == "darwin"
? process.env.HOME + "/Library/Application Support"
: process.env.HOME + "/.config");
var configFolder = path.join(appDataFolder, "FreeDATA");
var configPath = path.join(configFolder, "config.json");
var config = require(configPath);
const contrib = [
"DK5SM",
"DL4IAZ",
"DB1UJ",
"EI3HIB",
"VK5DGR",
"EI7IG",
"N2KIQ",
"KT4WO",
"DF7MH",
"G0HWW",
"N1QM",
"LA3QMA",
];
//let elements = document.querySelectorAll('[id^="hamlib_"]'); // get all elements starting with...
const hamlib_elements = [
"hamlib_deviceid",
"hamlib_deviceport",
"hamlib_stop_bits",
"hamlib_data_bits",
"hamlib_handshake",
"hamlib_serialspeed",
"hamlib_dtrstate",
"hamlib_pttprotocol",
"hamlib_ptt_port",
"hamlib_dcd",
"hamlib_rigctld_port",
"hamlib_rigctld_ip",
"hamlib_rigctld_path",
"hamlib_rigctld_server_port",
"hamlib_rigctld_custom_args",
];
// SET dbfs LEVEL GLOBAL
// this is an attempt of reducing CPU LOAD
// we are going to check if we have unequal values before we start calculating again
var dbfs_level_raw = 0;
var noise_level_raw = 0;
//Global version variable
var appVer = null;
//Track the number of times TNC has been started
//So that warning is shown when using auto start and 2nd start
//if hamlib is not running
var tncStartCount = 0;
// START INTERVALL COMMAND EXECUTION FOR STATES
//setInterval(sock.getRxBuffer, 1000);
// WINDOW LISTENER
window.addEventListener("DOMContentLoaded", () => {
// save frequency event listener
document.getElementById("saveFrequency").addEventListener("click", () => {
var freq = document.getElementById("newFrequency").value;
console.log(freq);
let Data = {
type: "set",
command: "frequency",
frequency: freq,
};
ipcRenderer.send("run-tnc-command", Data);
});
// enter button for input field
document
.getElementById("newFrequency")
.addEventListener("keypress", function (event) {
if (event.key === "Enter") {
event.preventDefault();
document.getElementById("saveFrequency").click();
}
});
// save mode event listener
document.getElementById("saveModePKTUSB").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "PKTUSB",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeDIGU").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "DIGU",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeDIGL").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "DIGL",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeUSB").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "USB",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeLSB").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "LSB",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeAM").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "AM",
};
ipcRenderer.send("run-tnc-command", Data);
});
// save mode event listener
document.getElementById("saveModeFM").addEventListener("click", () => {
let Data = {
type: "set",
command: "mode",
mode: "FM",
};
ipcRenderer.send("run-tnc-command", Data);
});
// start stop audio recording event listener
document
.getElementById("startStopRecording")
.addEventListener("click", () => {
let Data = {
type: "set",
command: "record_audio",
};
ipcRenderer.send("run-tnc-command", Data);
});
document
.getElementById("received_files_folder")
.addEventListener("click", () => {
ipcRenderer.send("get-folder-path", {
title: "Title",
action: "return-folder-paths-received_files_folder",
});
ipcRenderer.on(
"return-folder-paths-received_files_folder",
(event, data) => {
document.getElementById("received_files_folder").value =
data.path.filePaths[0];
config.received_files_folder = data.path.filePaths[0];
FD.saveConfig(config, configPath);
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
},
);
});
document
.getElementById("shared_folder_path")
.addEventListener("click", () => {
ipcRenderer.send("get-folder-path", {
title: "Title",
action: "return-folder-paths-shared_folder_path",
});
ipcRenderer.on(
"return-folder-paths-shared_folder_path",
(event, data) => {
document.getElementById("shared_folder_path").value =
data.path.filePaths[0];
config.shared_folder_path = data.path.filePaths[0];
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
},
);
});
document
.getElementById("openReceivedFilesFolder")
.addEventListener("click", () => {
ipcRenderer.send("open-folder", {
path: config.received_files_folder,
});
});
/*
// ENABLE BOOTSTRAP POPOVERS EVERYWHERE
// https://getbootstrap.com/docs/5.0/components/popovers/#example-enable-popovers-everywhere
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl)
})
*/
// ENABLE TOOLTIPS EVERYWHERE
// https://getbootstrap.com/docs/5.1/components/tooltips/
var tooltipTriggerList = [].slice.call(
document.querySelectorAll('[data-bs-toggle="tooltip"]'),
);
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// LOAD SETTINGS
// load settings by function
loadSettings(hamlib_elements);
document.getElementById("tnc_adress").value = config.tnc_host;
document.getElementById("tnc_port").value = config.tnc_port;
callsign_and_ssid = config.mycall.split("-");
callsign = callsign_and_ssid[0];
ssid = callsign_and_ssid[1];
document.getElementById("myCall").value = callsign;
//document.title = document.title + ' - Call: ' + config.mycall;
updateTitle();
document.getElementById("myCallSSID").value = ssid;
document.getElementById("myGrid").value = config.mygrid;
// hamlib settings
document.getElementById("hamlib_deviceid").value = config.hamlib_deviceid;
document.getElementById("hamlib_rigctld_ip").value = config.hamlib_rigctld_ip;
document.getElementById("hamlib_rigctld_port").value =
config.hamlib_rigctld_port;
document.getElementById("tci_ip").value = config.tci_ip;
document.getElementById("tci_port").value = config.tci_port;
document.getElementById("hamlib_rigctld_path").value =
config.hamlib_rigctld_path;
document.getElementById("hamlib_rigctld_server_port").value =
config.hamlib_rigctld_server_port;
// running this in try catch for setting default value in case of wrong beacon intervals
// https://stackoverflow.com/a/69293164
console.log(config.beacon_interval);
let selectElement = document.getElementById("beaconInterval");
let optionValues = [...selectElement.options].map((o) => o.value);
console.log(optionValues);
if (optionValues.includes(config.beacon_interval)) {
document.getElementById("beaconInterval").value = config.beacon_interval;
} else {
document.getElementById("beaconInterval").value = "300";
}
document.getElementById("scatterSwitch").value = config.enable_scatter;
document.getElementById("fftSwitch").value = config.enable_fft;
document.getElementById("received_files_folder").value =
config.received_files_folder;
if (config.enable_scatter == "True") {
document.getElementById("scatterSwitch").checked = true;
} else {
document.getElementById("scatterSwitch").checked = false;
}
document.getElementById("shared_folder_path").value =
config.shared_folder_path;
if (config.enable_auto_retry == "True") {
document.getElementById("enable_auto_retry").checked = true;
} else {
document.getElementById("enable_auto_retry").checked = false;
}
document.getElementById("max_retry_attempts").value =
config.max_retry_attempts;
if (config.enable_request_profile == "True") {
document.getElementById("enable_request_profile").checked = true;
} else {
document.getElementById("enable_request_profile").checked = false;
}
if (config.enable_request_shared_folder == "True") {
document.getElementById("enable_request_shared_folder").checked = true;
} else {
document.getElementById("enable_request_shared_folder").checked = false;
}
if (config.enable_is_writing == "True") {
document.getElementById("enable_is_writing").checked = true;
} else {
document.getElementById("enable_is_writing").checked = false;
}
if (config.enable_fft == "True") {
document.getElementById("fftSwitch").checked = true;
} else {
document.getElementById("fftSwitch").checked = false;
}
if (config.low_bandwidth_mode == "True") {
document.getElementById("250HzModeSwitch").checked = true;
} else {
document.getElementById("250HzModeSwitch").checked = false;
}
if (config.high_graphics == "True") {
document.getElementById("GraphicsSwitch").checked = true;
} else {
document.getElementById("GraphicsSwitch").checked = false;
}
if (config.enable_fsk == "True") {
document.getElementById("fskModeSwitch").checked = true;
} else {
document.getElementById("fskModeSwitch").checked = false;
}
if (config.respond_to_cq == "True") {
document.getElementById("respondCQSwitch").checked = true;
} else {
document.getElementById("respondCQSwitch").checked = false;
}
if (config.enable_explorer == "True") {
document.getElementById("ExplorerSwitch").checked = true;
} else {
document.getElementById("ExplorerSwitch").checked = false;
}
if (config.explorer_stats.toLowerCase() == "true") {
document.getElementById("ExplorerStatsSwitch").checked = true;
} else {
document.getElementById("ExplorerStatsSwitch").checked = false;
}
if (config.auto_tune == "True") {
document.getElementById("autoTuneSwitch").checked = true;
} else {
document.getElementById("autoTuneSwitch").checked = false;
}
if (config.auto_start == 1) {
document.getElementById("AutoStartSwitch").checked = true;
} else {
document.getElementById("AutoStartSwitch").checked = false;
}
if (config.enable_sys_notification == 1) {
document.getElementById("NotificationSwitch").checked = true;
} else {
document.getElementById("NotificationSwitch").checked = false;
}
if (config.enable_mesh_features.toLowerCase() == "true") {
document.getElementById("list-mesh-list").style.visibility = "visible";
document.getElementById("list-mesh-list").style.display = "block";
document.getElementById("enableMeshSwitch").checked = true;
} else {
document.getElementById("list-mesh-list").style.visibility = "hidden";
document.getElementById("list-mesh-list").style.display = "none";
document.getElementById("enableMeshSwitch").checked = false;
}
// theme selector
changeGuiDesign(config.theme);
// Update channel selector
document.getElementById("update_channel_selector").value =
config.update_channel;
document.getElementById("updater_channel").innerHTML = escape(
config.update_channel,
);
// Update tuning range fmin fmax
document.getElementById("tuning_range_fmin").value = config.tuning_range_fmin;
document.getElementById("tuning_range_fmax").value = config.tuning_range_fmax;
//Update TX delay
document.getElementById("tx_delay").value = config.tx_delay;
// Update TX Audio Level
document.getElementById("audioLevelTXvalue").innerHTML = parseInt(
config.tx_audio_level,
);
document.getElementById("audioLevelTX").value = parseInt(
config.tx_audio_level,
);
// Update RX Buffer Size
document.getElementById("rx_buffer_size").value = config.rx_buffer_size;
if (config.spectrum == "waterfall") {
document.getElementById("waterfall-scatter-switch1").checked = true;
document.getElementById("waterfall-scatter-switch2").checked = false;
document.getElementById("waterfall-scatter-switch3").checked = false;
document.getElementById("waterfall").style.visibility = "visible";
document.getElementById("waterfall").style.height = "100%";
document.getElementById("waterfall").style.display = "block";
document.getElementById("scatter").style.height = "0px";
document.getElementById("scatter").style.visibility = "hidden";
document.getElementById("scatter").style.display = "none";
document.getElementById("chart").style.height = "0px";
document.getElementById("chart").style.visibility = "hidden";
document.getElementById("chart").style.display = "none";
} else if (config.spectrum == "scatter") {
document.getElementById("waterfall-scatter-switch1").checked = false;
document.getElementById("waterfall-scatter-switch2").checked = true;
document.getElementById("waterfall-scatter-switch3").checked = false;
document.getElementById("waterfall").style.visibility = "hidden";
document.getElementById("waterfall").style.height = "0px";
document.getElementById("waterfall").style.display = "none";
document.getElementById("scatter").style.height = "100%";
document.getElementById("scatter").style.visibility = "visible";
document.getElementById("scatter").style.display = "block";
document.getElementById("chart").style.visibility = "hidden";
document.getElementById("chart").style.height = "0px";
document.getElementById("chart").style.display = "none";
} else {
document.getElementById("waterfall-scatter-switch1").checked = false;
document.getElementById("waterfall-scatter-switch2").checked = false;
document.getElementById("waterfall-scatter-switch3").checked = true;
document.getElementById("waterfall").style.visibility = "hidden";
document.getElementById("waterfall").style.height = "0px";
document.getElementById("waterfall").style.display = "none";
document.getElementById("scatter").style.height = "0px";
document.getElementById("scatter").style.visibility = "hidden";
document.getElementById("scatter").style.display = "none";
document.getElementById("chart").style.visibility = "visible";
document.getElementById("chart").style.height = "100%";
document.getElementById("chart").style.display = "block";
}
// radio control element
if (config.radiocontrol == "rigctld") {
document.getElementById("radio-control-switch-disabled").checked = false;
document.getElementById("radio-control-switch-rigctld").checked = true;
document.getElementById("radio-control-switch-tci").checked = false;
document.getElementById("radio-control-disabled").style.visibility =
"hidden";
document.getElementById("radio-control-disabled").style.display = "none";
document.getElementById("radio-control-tci").style.display = "none";
document.getElementById("radio-control-tci").style.visibility = "hidden";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-rigctld").style.visibility =
"visible";
document.getElementById("radio-control-rigctld").style.display = "block";
} else if (config.radiocontrol == "tci") {
document.getElementById("radio-control-switch-disabled").checked = false;
document.getElementById("radio-control-switch-rigctld").checked = false;
document.getElementById("radio-control-switch-tci").checked = true;
document.getElementById("radio-control-disabled").style.visibility =
"hidden";
document.getElementById("radio-control-disabled").style.display = "none";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-rigctld").style.visibility =
"hidden";
document.getElementById("radio-control-rigctld").style.display = "none";
document.getElementById("radio-control-tci").style.visibility = "visible";
document.getElementById("radio-control-tci").style.display = "block";
} else {
document.getElementById("radio-control-switch-disabled").checked = true;
document.getElementById("radio-control-switch-rigctld").checked = false;
document.getElementById("radio-control-switch-tci").checked = false;
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-tci").style.display = "none";
document.getElementById("radio-control-tci").style.visibility = "hidden";
document.getElementById("radio-control-rigctld").style.visibility =
"hidden";
document.getElementById("radio-control-rigctld").style.display = "none";
}
// remote tnc
if (config.tnclocation == "remote") {
document.getElementById("local-remote-switch1").checked = false;
document.getElementById("local-remote-switch2").checked = true;
document.getElementById("remote-tnc-field").style.visibility = "visible";
toggleClass("remote-tnc-field", "d-none", false);
} else {
document.getElementById("local-remote-switch1").checked = true;
document.getElementById("local-remote-switch2").checked = false;
document.getElementById("remote-tnc-field").style.visibility = "hidden";
toggleClass("remote-tnc-field", "d-none", true);
}
// Create spectrum object on canvas with ID "waterfall"
global.spectrum = new Spectrum("waterfall", {
spectrumPercent: 0,
wf_rows: 192, //Assuming 1 row = 1 pixe1, 192 is the height of the spectrum container
});
//Set waterfalltheme
document.getElementById("wftheme_selector").value = config.wftheme;
spectrum.setColorMap(config.wftheme);
document.getElementById("list-info-list").addEventListener("click", () => {
document.getElementById("aboutVersion").innerText = appVer;
let maxcol = 3;
let col = 2;
let shuffled = contrib
.map((value) => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort)
.map(({ value }) => value);
let list = "
DJ2LS";
let list2 = "";
let list3 = "";
shuffled.forEach((element) => {
switch (col) {
case 1:
list += "" + element + "";
break;
case 2:
list2 += "" + element + "";
break;
case 3:
list3 += "" + element + "";
break;
}
col = col + 1;
if (col > maxcol) {
col = 1;
}
});
//list+="";
divContrib.innerHTML = "";
divContrib2.innerHTML = "";
divContrib3.innerHTML = "";
//console.log(shuffled)
});
// on click radio control toggle view
// disabled
document
.getElementById("radio-control-switch-disabled")
.addEventListener("click", () => {
//document.getElementById("hamlib_info_field").innerHTML =
// "Disables TNC rig control";
document.getElementById("radio-control-disabled").style.display = "block";
document.getElementById("radio-control-disabled").style.visibility =
"visible";
document.getElementById("radio-control-tci").style.display = "none";
document.getElementById("radio-control-tci").style.visibility = "hidden";
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-rigctld").style.visibility =
"hidden";
document.getElementById("radio-control-rigctld").style.display = "none";
config.radiocontrol = "disabled";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// // radio settings 'rigctld' event listener
document
.getElementById("radio-control-switch-rigctld")
.addEventListener("click", () => {
//document.getElementById("hamlib_info_field").innerHTML =
// "Edit your rigctld settings and start and stop rigctld .";
document.getElementById("radio-control-disabled").style.display = "none";
document.getElementById("radio-control-disabled").style.visibility =
"hidden";
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-tci").style.display = "none";
document.getElementById("radio-control-tci").style.visibility = "hidden";
document.getElementById("radio-control-rigctld").style.visibility =
"visible";
document.getElementById("radio-control-rigctld").style.display = "block";
config.radiocontrol = "rigctld";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// // radio settings 'rigctld' event listener
document
.getElementById("radio-control-switch-tci")
.addEventListener("click", () => {
//document.getElementById("hamlib_info_field").innerHTML =
// "Edit your rigctld settings and start and stop rigctld .";
document.getElementById("radio-control-disabled").style.display = "none";
document.getElementById("radio-control-disabled").style.visibility =
"hidden";
document.getElementById("radio-control-rigctld").style.display = "none";
document.getElementById("radio-control-rigctld").style.visibility =
"hidden";
document.getElementById("radio-control-help").style.display = "none";
document.getElementById("radio-control-help").style.visibility = "hidden";
document.getElementById("radio-control-tci").style.visibility = "visible";
document.getElementById("radio-control-tci").style.display = "block";
config.radiocontrol = "tci";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
document
.getElementById("btnHamlibCopyCommand")
.addEventListener("click", () => {
hamlib_params();
let rigctld = document.getElementById("hamlib_rigctld_path").value;
//Escape spaces in executable file
switch (os.platform().toLowerCase()) {
case "darwin":
case "linux":
rigctld = rigctld.replace(" ", "\\ ");
break;
case "win32":
case "win64":
if (rigctld.indexOf(" ") > -1) rigctld = '"' + rigctld + '"';
break;
default:
console.log("Unhandled OS Platform: ", os.platform());
break;
}
rigctld +=
" " + document.getElementById("hamlib_rigctld_command").value + " -vv";
document.getElementById("btnHamlibCopyCommandBi").classList =
"bi bi-clipboard2-check-fill";
clipboard.writeText(rigctld);
setTimeout(function () {
document.getElementById("btnHamlibCopyCommandBi").classList =
"bi bi-clipboard";
}, 2000);
});
document
.getElementById("hamlib_rigctld_path")
.addEventListener("click", () => {
ipcRenderer.send("get-file-path", {
title: "Title",
action: "return-file-path-hamlib_rigctld_path",
});
ipcRenderer.on("return-file-path-hamlib_rigctld_path", (event, data) => {
rigctldPath = data.path.filePaths[0];
document.getElementById("hamlib_rigctld_path").value = rigctldPath;
config.hamlib_rigctld_path = rigctldPath;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
hamlib_params();
});
});
// radio settings 'hamlib_rigctld_server_port' event listener
document
.getElementById("hamlib_rigctld_server_port")
.addEventListener("change", () => {
config.hamlib_rigctld_server_port = document.getElementById(
"hamlib_rigctld_server_port",
).value;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
hamlib_params();
});
// hamlib bulk event listener for saving settings
hamlib_elements.forEach(function (elem) {
try {
document.getElementById(elem).addEventListener("change", function () {
config[elem] = document.getElementById(elem).value;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
console.log(config);
hamlib_params();
});
} catch (e) {
console.log(e);
console.log(elem);
}
});
document
.getElementById("hamlib_rigctld_start")
.addEventListener("click", () => {
var rigctldPath = document.getElementById("hamlib_rigctld_path").value;
var paramList = hamlib_params();
let Data = {
path: rigctldPath,
parameters: paramList,
};
ipcRenderer.send("request-start-rigctld", Data);
});
hamlib_params = function () {
var paramList = [];
// hamlib stopbits setting
if (document.getElementById("hamlib_deviceid").value !== "-- ignore --") {
var hamlib_deviceid = document.getElementById("hamlib_deviceid").value;
paramList = paramList.concat("--model=" + hamlib_deviceid);
}
// hamlib deviceport setting
if (document.getElementById("hamlib_deviceport").value !== "ignore") {
var hamlib_deviceport =
document.getElementById("hamlib_deviceport").value;
paramList = paramList.concat("--rig-file=" + hamlib_deviceport);
}
// hamlib serialspeed setting
if (document.getElementById("hamlib_serialspeed").value !== "ignore") {
var hamlib_serialspeed =
document.getElementById("hamlib_serialspeed").value;
paramList = paramList.concat("--serial-speed=" + hamlib_serialspeed);
}
// hamlib databits setting
if (document.getElementById("hamlib_data_bits").value !== "ignore") {
var hamlib_data_bits = document.getElementById("hamlib_data_bits").value;
paramList = paramList.concat("--set-conf=data_bits=" + hamlib_data_bits);
}
// hamlib stopbits setting
if (document.getElementById("hamlib_stop_bits").value !== "ignore") {
var hamlib_stop_bits = document.getElementById("hamlib_stop_bits").value;
paramList = paramList.concat("--set-conf=stop_bits=" + hamlib_stop_bits);
}
// hamlib handshake setting
if (document.getElementById("hamlib_handshake").value !== "ignore") {
var hamlib_handshake = document.getElementById("hamlib_handshake").value;
paramList = paramList.concat(
"--set-conf=serial_handshake=" + hamlib_handshake,
);
}
// hamlib dcd setting
if (document.getElementById("hamlib_dcd").value !== "ignore") {
var hamlib_dcd = document.getElementById("hamlib_dcd").value;
paramList = paramList.concat("--dcd-type=" + hamlib_dcd);
}
// hamlib ptt port
if (document.getElementById("hamlib_ptt_port").value !== "ignore") {
var hamlib_ptt_port = document.getElementById("hamlib_ptt_port").value;
paramList = paramList.concat("--ptt-file=" + hamlib_ptt_port);
}
// hamlib ptt type
if (document.getElementById("hamlib_pttprotocol").value !== "ignore") {
var hamlib_ptt_type = document.getElementById("hamlib_pttprotocol").value;
paramList = paramList.concat("--ptt-type=" + hamlib_ptt_type);
}
// hamlib dtr state
if (document.getElementById("hamlib_dtrstate").value !== "ignore") {
var hamlib_dtrstate = document.getElementById("hamlib_dtrstate").value;
paramList = paramList.concat("--set-conf=dtr_state=" + hamlib_dtrstate);
}
var hamlib_rigctld_server_port = document.getElementById(
"hamlib_rigctld_server_port",
).value;
paramList = paramList.concat("--port=" + hamlib_rigctld_server_port);
//Custom rigctld arguments to pass to rigctld
var hamlib_rigctld_custom_args = document.getElementById(
"hamlib_rigctld_custom_args",
).value;
paramList = paramList.concat(hamlib_rigctld_custom_args);
document.getElementById("hamlib_rigctld_command").value =
paramList.join(" "); // join removes the commas
console.log(paramList);
//console.log(rigctldPath);
return paramList;
};
document
.getElementById("hamlib_rigctld_stop")
.addEventListener("click", () => {
ipcRenderer.send("request-stop-rigctld", {
path: "123",
parameters: "--version",
});
});
// on click waterfall scatter toggle view
// waterfall
document
.getElementById("waterfall-scatter-switch1")
.addEventListener("click", () => {
document.getElementById("chart").style.visibility = "hidden";
document.getElementById("chart").style.display = "none";
document.getElementById("chart").style.height = "0px";
document.getElementById("scatter").style.height = "0px";
document.getElementById("scatter").style.display = "none";
document.getElementById("scatter").style.visibility = "hidden";
document.getElementById("waterfall").style.display = "block";
document.getElementById("waterfall").style.visibility = "visible";
document.getElementById("waterfall").style.height = "100%";
config.spectrum = "waterfall";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// scatter
document
.getElementById("waterfall-scatter-switch2")
.addEventListener("click", () => {
document.getElementById("scatter").style.display = "block";
document.getElementById("scatter").style.visibility = "visible";
document.getElementById("scatter").style.height = "100%";
document.getElementById("waterfall").style.visibility = "hidden";
document.getElementById("waterfall").style.height = "0px";
document.getElementById("waterfall").style.display = "none";
document.getElementById("chart").style.visibility = "hidden";
document.getElementById("chart").style.height = "0px";
document.getElementById("chart").style.display = "none";
config.spectrum = "scatter";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// chart
document
.getElementById("waterfall-scatter-switch3")
.addEventListener("click", () => {
document.getElementById("waterfall").style.visibility = "hidden";
document.getElementById("waterfall").style.height = "0px";
document.getElementById("waterfall").style.display = "none";
document.getElementById("scatter").style.height = "0px";
document.getElementById("scatter").style.visibility = "hidden";
document.getElementById("scatter").style.display = "none";
document.getElementById("chart").style.height = "100%";
document.getElementById("chart").style.display = "block";
document.getElementById("chart").style.visibility = "visible";
config.spectrum = "chart";
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// on click remote tnc toggle view
document
.getElementById("local-remote-switch1")
.addEventListener("click", () => {
document.getElementById("local-remote-switch1").checked = true;
document.getElementById("local-remote-switch2").checked = false;
document.getElementById("remote-tnc-field").style.visibility = "hidden";
config.tnclocation = "localhost";
toggleClass("remote-tnc-field", "d-none", true);
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
document
.getElementById("local-remote-switch2")
.addEventListener("click", () => {
document.getElementById("local-remote-switch1").checked = false;
document.getElementById("local-remote-switch2").checked = true;
document.getElementById("remote-tnc-field").style.visibility = "visible";
config.tnclocation = "remote";
toggleClass("remote-tnc-field", "d-none", false);
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// on change ping callsign
document.getElementById("dxCall").addEventListener("change", () => {
document.getElementById("dataModalDxCall").value =
document.getElementById("dxCall").value;
});
// on change ping callsign
document.getElementById("dataModalDxCall").addEventListener("change", () => {
document.getElementById("dxCall").value =
document.getElementById("dataModalDxCall").value;
});
// on change port and host
document.getElementById("tnc_adress").addEventListener("change", () => {
console.log(document.getElementById("tnc_adress").value);
config.tnc_host = document.getElementById("tnc_adress").value;
config.daemon_host = document.getElementById("tnc_adress").value;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
let Data = {
port: document.getElementById("tnc_port").value,
adress: document.getElementById("tnc_adress").value,
};
ipcRenderer.send("request-update-tnc-ip", Data);
Data = {
port: parseInt(document.getElementById("tnc_port").value) + 1,
adress: document.getElementById("tnc_adress").value,
};
ipcRenderer.send("request-update-daemon-ip", Data);
});
// on change tnc port
document.getElementById("tnc_port").addEventListener("change", () => {
config.tnc_port = document.getElementById("tnc_port").value;
config.daemon_port =
parseInt(document.getElementById("tnc_port").value) + 1;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
let Data = {
port: document.getElementById("tnc_port").value,
adress: document.getElementById("tnc_adress").value,
};
ipcRenderer.send("request-update-tnc-ip", Data);
Data = {
port: parseInt(document.getElementById("tnc_port").value) + 1,
adress: document.getElementById("tnc_adress").value,
};
ipcRenderer.send("request-update-daemon-ip", Data);
});
// on change audio TX Level
document.getElementById("audioLevelTX").addEventListener("change", () => {
var tx_audio_level = parseInt(
document.getElementById("audioLevelTX").value,
);
document.getElementById("audioLevelTXvalue").innerHTML = tx_audio_level;
config.tx_audio_level = tx_audio_level;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
let Data = {
command: "set_tx_audio_level",
tx_audio_level: tx_audio_level,
};
ipcRenderer.send("run-tnc-command", Data);
});
document.getElementById("sendTestFrame").addEventListener("click", () => {
let Data = {
type: "set",
command: "send_test_frame",
};
ipcRenderer.send("run-tnc-command", Data);
});
// saveMyCall button clicked
document.getElementById("myCall").addEventListener("input", () => {
callsign = document.getElementById("myCall").value;
ssid = document.getElementById("myCallSSID").value;
callsign_ssid = callsign.toUpperCase() + "-" + ssid;
config.mycall = callsign_ssid;
// split document title by looking for Call then split and update it
//var documentTitle = document.title.split('Call:')
//document.title = documentTitle[0] + 'Call: ' + callsign_ssid;
updateTitle(callsign_ssid);
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
daemon.saveMyCall(callsign_ssid);
});
// saveMyGrid button clicked
document.getElementById("myGrid").addEventListener("input", () => {
grid = document.getElementById("myGrid").value;
config.mygrid = grid;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
daemon.saveMyGrid(grid);
});
// startPing button clicked
document.getElementById("sendPing").addEventListener("click", () => {
var dxcallsign = document.getElementById("dxCall").value.toUpperCase();
if (dxcallsign == "" || dxcallsign == null || dxcallsign == undefined)
return;
pauseButton(document.getElementById("sendPing"), 2000);
sock.sendPing(dxcallsign);
});
// dataModalstartPing button clicked
document.getElementById("dataModalSendPing").addEventListener("click", () => {
var dxcallsign = document.getElementById("dataModalDxCall").value;
dxcallsign = dxcallsign.toUpperCase();
sock.sendPing(dxcallsign);
});
// close app, update and restart
document
.getElementById("update_and_install")
.addEventListener("click", () => {
ipcRenderer.send("request-restart-and-install");
});
/*disabled because it's causing confusion TODO: remove entire code some day
// open arq session
document.getElementById("openARQSession").addEventListener("click", () => {
var dxcallsign = document.getElementById("dataModalDxCall").value;
dxcallsign = dxcallsign.toUpperCase();
sock.connectARQ(dxcallsign);
});
// close arq session
document.getElementById("closeARQSession").addEventListener("click", () => {
sock.disconnectARQ();
});
*/
// sendCQ button clicked
document.getElementById("sendCQ").addEventListener("click", () => {
pauseButton(document.getElementById("sendCQ"), 2000);
sock.sendCQ();
});
// Start beacon button clicked
document.getElementById("startBeacon").addEventListener("click", () => {
let bcn = document.getElementById("startBeacon");
bcn.disabled = true;
interval = document.getElementById("beaconInterval").value;
//Use class list to determine state of beacon, secondary == off
if (bcn.className.toLowerCase().indexOf("secondary") > 0) {
//Stopped; let us start it
sock.startBeacon(interval);
} else {
sock.stopBeacon();
}
config.beacon_interval = interval;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
bcn.disabled = false;
});
// enable_auto_retry Switch clicked
document.getElementById("enable_auto_retry").addEventListener("click", () => {
console.log(document.getElementById("enable_auto_retry").checked);
if (document.getElementById("enable_auto_retry").checked == true) {
config.enable_auto_retry = "True";
} else {
config.enable_auto_retry = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// max_retry_attempts Switch clicked
document
.getElementById("max_retry_attempts")
.addEventListener("change", () => {
console.log(document.getElementById("max_retry_attempts").value);
config.max_retry_attempts =
document.getElementById("max_retry_attempts").value;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// sendscatter Switch clicked
document.getElementById("scatterSwitch").addEventListener("click", () => {
console.log(document.getElementById("scatterSwitch").checked);
if (document.getElementById("scatterSwitch").checked == true) {
config.enable_scatter = "True";
} else {
config.enable_scatter = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// sendfft Switch clicked
document.getElementById("fftSwitch").addEventListener("click", () => {
if (document.getElementById("fftSwitch").checked == true) {
config.enable_fft = "True";
} else {
config.enable_fft = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable 500z Switch clicked
document.getElementById("250HzModeSwitch").addEventListener("click", () => {
if (document.getElementById("250HzModeSwitch").checked == true) {
config.low_bandwidth_mode = "True";
} else {
config.low_bandwidth_mode = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable response to cq clicked
document.getElementById("respondCQSwitch").addEventListener("click", () => {
if (document.getElementById("respondCQSwitch").checked == true) {
config.respond_to_cq = "True";
} else {
config.respond_to_cq = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable explorer Switch clicked
document.getElementById("ExplorerSwitch").addEventListener("click", () => {
if (document.getElementById("ExplorerSwitch").checked == true) {
config.enable_explorer = "True";
} else {
config.enable_explorer = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable explorer stats Switch clicked
document
.getElementById("ExplorerStatsSwitch")
.addEventListener("click", () => {
if (document.getElementById("ExplorerStatsSwitch").checked == true) {
config.explorer_stats = "True";
} else {
config.explorer_stats = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable autotune Switch clicked
document.getElementById("autoTuneSwitch").addEventListener("click", () => {
if (document.getElementById("autoTuneSwitch").checked == true) {
config.auto_tune = "True";
} else {
config.auto_tune = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
//Handle change of fancy graphics
document.getElementById("GraphicsSwitch").addEventListener("click", () => {
if (document.getElementById("GraphicsSwitch").checked == true) {
config.high_graphics = "True";
} else {
config.high_graphics = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
set_CPU_mode();
});
//Handle change of Auto-start settings
document.getElementById("AutoStartSwitch").addEventListener("click", () => {
if (document.getElementById("AutoStartSwitch").checked == true) {
config.auto_start = 1;
} else {
config.auto_start = 0;
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
//Handle change of Notification settings
document
.getElementById("NotificationSwitch")
.addEventListener("click", () => {
if (document.getElementById("NotificationSwitch").checked == true) {
config.enable_sys_notification = 1;
} else {
config.enable_sys_notification = 0;
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable fsk Switch clicked
document.getElementById("fskModeSwitch").addEventListener("click", () => {
if (document.getElementById("fskModeSwitch").checked == true) {
config.enable_fsk = "True";
} else {
config.enable_fsk = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable MESH Switch clicked
document.getElementById("enableMeshSwitch").addEventListener("click", () => {
if (document.getElementById("enableMeshSwitch").checked == true) {
config.enable_mesh_features = "True";
document.getElementById("list-mesh-list").style.visibility = "visible";
document.getElementById("list-mesh-list").style.display = "block";
} else {
config.enable_mesh_features = "False";
document.getElementById("list-mesh-list").style.visibility = "hidden";
document.getElementById("list-mesh-list").style.display = "none";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable is writing switch clicked
document.getElementById("enable_is_writing").addEventListener("click", () => {
if (document.getElementById("enable_is_writing").checked == true) {
config.enable_is_writing = "True";
} else {
config.enable_is_writing = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// enable enable_request_shared_folder switch clicked
document
.getElementById("enable_request_shared_folder")
.addEventListener("click", () => {
if (
document.getElementById("enable_request_shared_folder").checked == true
) {
config.enable_request_shared_folder = "True";
} else {
config.enable_request_shared_folder = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
//Update file list after setting change
ipcRenderer.send("read-files-in-folder", {
folder: config.shared_folder_path.toString(),
});
});
// enable enable_request_profile switch clicked
document
.getElementById("enable_request_profile")
.addEventListener("click", () => {
if (document.getElementById("enable_request_profile").checked == true) {
config.enable_request_profile = "True";
} else {
config.enable_request_profile = "False";
}
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// Tuning range clicked
document.getElementById("tuning_range_fmin").addEventListener("click", () => {
var tuning_range_fmin = document.getElementById("tuning_range_fmin").value;
config.tuning_range_fmin = tuning_range_fmin;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
document.getElementById("tuning_range_fmax").addEventListener("click", () => {
var tuning_range_fmax = document.getElementById("tuning_range_fmax").value;
config.tuning_range_fmax = tuning_range_fmax;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
document.getElementById("tx_delay").addEventListener("click", () => {
var tx_delay = document.getElementById("tx_delay").value;
config.tx_delay = tx_delay;
FD.saveConfig(config, configPath);
});
// Theme selector clicked
document.getElementById("theme_selector").addEventListener("change", () => {
/*
var theme = document.getElementById("theme_selector").value;
if (theme != "default") {
var theme_path =
"../node_modules/bootswatch/dist/" + theme + "/bootstrap.min.css";
} else {
var theme_path = "../node_modules/bootstrap/dist/css/bootstrap.min.css";
}
*/
var theme = document.getElementById("theme_selector").value;
changeGuiDesign(theme);
config.theme = theme;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// Waterfall theme selector changed
document.getElementById("wftheme_selector").addEventListener("change", () => {
var wftheme = document.getElementById("wftheme_selector").value;
spectrum.setColorMap(wftheme);
config.wftheme = wftheme;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// Update channel selector changed
document
.getElementById("update_channel_selector")
.addEventListener("change", () => {
config.update_channel = document.getElementById(
"update_channel_selector",
).value;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
console.log("Autoupdate channel changed to ", config.update_channel);
});
// rx buffer size selector clicked
document.getElementById("rx_buffer_size").addEventListener("click", () => {
var rx_buffer_size = document.getElementById("rx_buffer_size").value;
config.rx_buffer_size = rx_buffer_size;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
//screen size
window.addEventListener("resize", () => {
config.screen_height = window.innerHeight;
config.screen_width = window.innerWidth;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
});
// Explorer button clicked
document.getElementById("openExplorer").addEventListener("click", () => {
shell.openExternal(
"https://explorer.freedata.app/?myCall=" +
document.getElementById("myCall").value,
);
});
// Stats button clicked
document.getElementById("btnStats").addEventListener("click", () => {
shell.openExternal("https://statistics.freedata.app");
});
// GH Link clicked
document.getElementById("fdWww").addEventListener("click", () => {
shell.openExternal("https://freedata.app");
});
// GH Link clicked
document.getElementById("ghUrl").addEventListener("click", () => {
shell.openExternal("https://github.com/DJ2LS/FreeDATA");
});
// Wiki Link clicked
document.getElementById("wikiUrl").addEventListener("click", () => {
shell.openExternal("https://wiki.freedata.app");
});
// Discord Link clicked
document.getElementById("discordUrl").addEventListener("click", () => {
shell.openExternal("https://discord.freedata.app/");
});
// startTNC button clicked
document.getElementById("startTNC").addEventListener("click", () => {
tncStartCount++;
var tuning_range_fmin = document.getElementById("tuning_range_fmin").value;
var tuning_range_fmax = document.getElementById("tuning_range_fmax").value;
var rigctld_ip = document.getElementById("hamlib_rigctld_ip").value;
var rigctld_port = document.getElementById("hamlib_rigctld_port").value;
var tci_ip = document.getElementById("tci_ip").value;
var tci_port = document.getElementById("tci_port").value;
var hamlib_rigctld_server_port = document.getElementById(
"hamlib_rigctld_server_port",
).value;
var deviceid = document.getElementById("hamlib_deviceid").value;
var deviceport = document.getElementById("hamlib_deviceport").value;
var serialspeed = document.getElementById("hamlib_serialspeed").value;
var pttprotocol = document.getElementById("hamlib_pttprotocol").value;
var hamlib_dcd = document.getElementById("hamlib_dcd").value;
var mycall = document.getElementById("myCall").value;
var ssid = document.getElementById("myCallSSID").value;
callsign_ssid = mycall.toUpperCase() + "-" + ssid;
var mygrid = document.getElementById("myGrid").value;
var rx_audio = document.getElementById("audio_input_selectbox").value;
var tx_audio = document.getElementById("audio_output_selectbox").value;
var pttport = document.getElementById("hamlib_ptt_port").value;
var data_bits = document.getElementById("hamlib_data_bits").value;
var stop_bits = document.getElementById("hamlib_stop_bits").value;
var handshake = document.getElementById("hamlib_handshake").value;
var tx_delay = document.getElementById("tx_delay").value;
if (document.getElementById("enableMeshSwitch").checked == true) {
var enable_mesh_features = "True";
document.getElementById("list-mesh-list").style.visibility = "visible";
document.getElementById("list-mesh-list").style.display = "block";
} else {
var enable_mesh_features = "False";
document.getElementById("list-mesh-list").style.visibility = "hidden";
document.getElementById("list-mesh-list").style.display = "none";
}
if (document.getElementById("scatterSwitch").checked == true) {
var enable_scatter = "True";
} else {
var enable_scatter = "False";
}
if (document.getElementById("fftSwitch").checked == true) {
var enable_fft = "True";
} else {
var enable_fft = "False";
}
if (document.getElementById("250HzModeSwitch").checked == true) {
var low_bandwidth_mode = "True";
} else {
var low_bandwidth_mode = "False";
}
if (document.getElementById("fskModeSwitch").checked == true) {
var enable_fsk = "True";
} else {
var enable_fsk = "False";
}
if (document.getElementById("respondCQSwitch").checked == true) {
var respond_to_cq = "True";
} else {
var respond_to_cq = "False";
}
if (document.getElementById("ExplorerSwitch").checked == true) {
var enable_explorer = "True";
} else {
var enable_explorer = "False";
}
if (document.getElementById("ExplorerStatsSwitch").checked == true) {
var explorer_stats = "True";
} else {
var explorer_stats = "False";
}
if (document.getElementById("autoTuneSwitch").checked == true) {
var auto_tune = "True";
} else {
var auto_tune = "False";
}
// loop through audio device list and select
for (
i = 0;
i < document.getElementById("audio_input_selectbox").length;
i++
) {
device = document.getElementById("audio_input_selectbox")[i];
if (device.value == rx_audio) {
console.log(device.text);
config.rx_audio = device.text;
}
}
// loop through audio device list and select
for (
i = 0;
i < document.getElementById("audio_output_selectbox").length;
i++
) {
device = document.getElementById("audio_output_selectbox")[i];
if (device.value == tx_audio) {
console.log(device.text);
config.tx_audio = device.text;
}
}
if (document.getElementById("radio-control-switch-rigctld").checked) {
var radiocontrol = "rigctld";
} else if (document.getElementById("radio-control-switch-tci").checked) {
var radiocontrol = "tci";
} else {
var radiocontrol = "disabled";
}
var tx_audio_level = document.getElementById("audioLevelTX").value;
var rx_buffer_size = document.getElementById("rx_buffer_size").value;
config.radiocontrol = radiocontrol;
config.mycall = callsign_ssid;
config.mygrid = mygrid;
config.hamlib_deviceid = deviceid;
config.hamlib_deviceport = deviceport;
config.hamlib_serialspeed = serialspeed;
config.hamlib_pttprotocol = pttprotocol;
config.hamlib_ptt_port = pttport;
config.hamlib_data_bits = data_bits;
config.hamlib_stop_bits = stop_bits;
config.hamlib_handshake = handshake;
config.hamlib_dcd = hamlib_dcd;
config.hamlib_rigctld_port = rigctld_port;
config.hamlib_rigctld_ip = rigctld_ip;
config.hamlib_rigctld_server_port = hamlib_rigctld_server_port;
config.enable_scatter = enable_scatter;
config.enable_fft = enable_fft;
config.enable_fsk = enable_fsk;
config.low_bandwidth_mode = low_bandwidth_mode;
config.tx_audio_level = tx_audio_level;
config.respond_to_cq = respond_to_cq;
config.rx_buffer_size = rx_buffer_size;
config.enable_explorer = enable_explorer;
config.explorer_stats = explorer_stats;
config.auto_tune = auto_tune;
config.tx_delay = tx_delay;
config.tci_ip = tci_ip;
config.tci_port = tci_port;
config.enable_mesh_features = enable_mesh_features;
//fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
FD.saveConfig(config, configPath);
//Display a message if hamlib control is enabled and not running
if (
config.radiocontrol == "rigctld" &&
rigctldActive == false &&
(config.auto_start == 0 || tncStartCount > 1)
) {
if (
!window.confirm(
"Rig control is set to hamlib/rigctl, but it doesn't appear to be running.\n\nPlease start rigctld (start button in Rig Control area), or use rigctl mode 'none'. If you're having issues starting rigctld please review the Hamlib tab in settings.\n\nClick OK to continue or cancel to abort.",
)
) {
return;
}
}
daemon.startTNC(
callsign_ssid,
mygrid,
rx_audio,
tx_audio,
radiocontrol,
deviceid,
deviceport,
pttprotocol,
pttport,
serialspeed,
data_bits,
stop_bits,
handshake,
rigctld_ip,
rigctld_port,
enable_fft,
enable_scatter,
low_bandwidth_mode,
tuning_range_fmin,
tuning_range_fmax,
enable_fsk,
tx_audio_level,
respond_to_cq,
rx_buffer_size,
enable_explorer,
explorer_stats,
auto_tune,
tx_delay,
tci_ip,
tci_port,
enable_mesh_features,
);
});
// stopTNC button clicked
document.getElementById("stopTNC").addEventListener("click", () => {
if (!confirm("Stop the TNC?")) return;
daemon.stopTNC();
});
// btnCleanDB button clicked
document.getElementById("btnCleanDB").addEventListener("click", () => {
document.getElementById("divCleanDBSpinner").classList.remove("invisible");
ipcRenderer.send("request-clean-db");
});
// TEST HAMLIB
document.getElementById("testHamlib").addEventListener("click", () => {
var data_bits = document.getElementById("hamlib_data_bits").value;
var stop_bits = document.getElementById("hamlib_stop_bits").value;
var handshake = document.getElementById("hamlib_handshake").value;
var pttport = document.getElementById("hamlib_ptt_port").value;
var rigctld_ip = document.getElementById("hamlib_rigctld_ip").value;
var rigctld_port = document.getElementById("hamlib_rigctld_port").value;
var deviceid = document.getElementById("hamlib_deviceid").value;
var deviceport = document.getElementById("hamlib_deviceport").value;
var serialspeed = document.getElementById("hamlib_serialspeed").value;
var pttprotocol = document.getElementById("hamlib_pttprotocol").value;
if (document.getElementById("radio-control-switch-disabled").checked) {
var radiocontrol = "disabled";
} else {
var radiocontrol = "rigctld";
}
daemon.testHamlib(
radiocontrol,
deviceid,
deviceport,
serialspeed,
pttprotocol,
pttport,
data_bits,
stop_bits,
handshake,
rigctld_ip,
rigctld_port,
);
});
// START TRANSMISSION
document.getElementById("startTransmission").addEventListener("click", () => {
var fileList = document.getElementById("dataModalFile").files;
console.log(fileList);
var reader = new FileReader();
reader.readAsBinaryString(fileList[0]);
//reader.readAsDataURL(fileList[0]);
reader.onload = function (e) {
// binary data
var data = e.target.result;
console.log(data);
let Data = {
command: "send_file",
dxcallsign: document
.getElementById("dataModalDxCall")
.value.toUpperCase(),
mode: document.getElementById("datamode").value,
frames: document.getElementById("framesperburst").value,
filetype: fileList[0].type,
filename: fileList[0].name,
data: data,
checksum: "123123123",
};
// only send command if dxcallsign entered and we have a file selected
if (document.getElementById("dataModalDxCall").value.length > 0) {
ipcRenderer.send("run-tnc-command", Data);
}
};
reader.onerror = function (e) {
// error occurred
console.log("Error : " + e.type);
};
});
// STOP TRANSMISSION
document.getElementById("stopTransmission").addEventListener("click", () => {
let Data = {
command: "stop_transmission",
};
ipcRenderer.send("run-tnc-command", Data);
});
// STOP TRANSMISSION AND CONNECRTION
document
.getElementById("stop_transmission_connection")
.addEventListener("click", () => {
let Data = {
command: "stop_transmission",
};
ipcRenderer.send("run-tnc-command", Data);
sock.disconnectARQ();
});
document.getElementById("thTime").addEventListener("click", () => {
if (hslLastSort == 0 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(0);
resetSortIcon();
});
document.getElementById("thFreq").addEventListener("click", () => {
if (hslLastSort == 1 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(1);
resetSortIcon();
});
document.getElementById("thDxcall").addEventListener("click", () => {
if (hslLastSort == 3 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(3);
resetSortIcon();
});
document.getElementById("thDxgrid").addEventListener("click", () => {
if (hslLastSort == 4 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(4);
resetSortIcon();
});
document.getElementById("thDist").addEventListener("click", () => {
if (hslLastSort == 5 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(5);
resetSortIcon();
});
document.getElementById("thType").addEventListener("click", () => {
if (hslLastSort == 6 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(6);
resetSortIcon();
});
document.getElementById("thSnr").addEventListener("click", () => {
if (hslLastSort == 7 && hslLastSortDir == "asc") hslLastSortDir = "desc";
else hslLastSortDir = "asc";
sorthslTable(7);
resetSortIcon();
});
autostart_rigctld();
});
//End of domcontentloaded
function resetSortIcon() {
document.getElementById("hslSort").remove();
let headers = document.querySelectorAll(
"#tblHeardStationList > thead > tr > th",
);
if (hslLastSortDir == "desc") text = "bi-sort-up";
else text = "bi-sort-down";
const sicon = document.createElement("i");
sicon.id = "hslSort";
sicon.classList.add("bi", text);
headers[hslLastSort].prepend(sicon);
}
function connectedStation(data) {
if (typeof data.dxcallsign == "undefined") {
return;
}
if (
!(typeof data.arq == "undefined") &&
data.arq.toLowerCase() == "session"
) {
var prefix = "w/ ";
} else {
switch (data.irs) {
case "True":
//We are receiving station
var prefix = "de ";
break;
case "False":
//We are sending station
var prefix = "to ";
break;
default:
//Shouldn't happen
console.trace("No data.irs data in tnc-message");
var prefix = "";
break;
}
}
document.getElementById("txtConnectedWith").textContent =
prefix + data.dxcallsign;
}
//Called by chat to turn off db clean spinner
ipcRenderer.on("action-update-dbclean-spinner", () => {
document.getElementById("divCleanDBSpinner").classList.add("invisible");
});
//Listen for events caused by tnc 'tnc-message' rx
ipcRenderer.on("action-update-reception-status", (event, arg) => {
var data = arg["data"][0];
var txprog = document.getElementById("transmission_progress");
ipcRenderer.send("request-show-electron-progressbar", data.percent);
txprog.setAttribute("aria-valuenow", data.percent);
txprog.setAttribute("style", "width:" + data.percent + "%;");
// SET TIME LEFT UNTIL FINIHED
if (typeof data.finished == "undefined") {
var time_left = "time left: estimating";
} else {
var arq_seconds_until_finish = data.finished;
var hours = Math.floor(arq_seconds_until_finish / 3600);
var minutes = Math.floor((arq_seconds_until_finish % 3600) / 60);
var seconds = arq_seconds_until_finish % 60;
if (hours < 0) {
hours = 0;
}
if (minutes < 0) {
minutes = 0;
}
if (seconds < 0) {
seconds = 0;
}
if (hours > 0) {
time_left =
"time left: ~" +
hours.toString().padStart(2, "0") +
":" +
minutes.toString().padStart(2, "0") +
"." +
seconds.toString().padStart(2, "0");
} else {
time_left =
"time left: ~" +
minutes.toString().padStart(2, "0") +
"." +
seconds.toString().padStart(2, "0");
}
}
var time_left = "" + time_left + " || Speed/min: ";
// SET BYTES PER MINUTE
if (typeof data.bytesperminute == "undefined") {
var arq_bytes_per_minute = 0;
} else {
var arq_bytes_per_minute = data.bytesperminute;
}
// SET BYTES PER MINUTE COMPRESSED
var compress = data.compression;
if (isNaN(compress)) {
compress = 1;
}
var arq_bytes_per_minute_compressed = Math.round(
arq_bytes_per_minute * compress,
);
console.log(arq_bytes_per_minute);
time_left +=
formatBytes(arq_bytes_per_minute, 1) +
" (comp: " +
formatBytes(arq_bytes_per_minute_compressed, 1) +
")";
document.getElementById("transmission_timeleft").innerHTML = time_left;
connectedStation(data);
});
//Listen for events caused by tnc 'tnc-message's tx
ipcRenderer.on("action-update-transmission-status", (event, arg) => {
var data = arg["data"][0];
var txprog = document.getElementById("transmission_progress");
ipcRenderer.send("request-show-electron-progressbar", data.percent);
txprog.setAttribute("aria-valuenow", data.percent);
txprog.setAttribute("style", "width:" + data.percent + "%;");
// SET TIME LEFT UNTIL FINIHED
if (typeof data.finished == "undefined") {
var time_left = "time left: estimating";
} else {
var arq_seconds_until_finish = data.finished;
var hours = Math.floor(arq_seconds_until_finish / 3600);
var minutes = Math.floor((arq_seconds_until_finish % 3600) / 60);
var seconds = arq_seconds_until_finish % 60;
if (hours < 0) {
hours = 0;
}
if (minutes < 0) {
minutes = 0;
}
if (seconds < 0) {
seconds = 0;
}
if (hours > 0) {
time_left =
"time left: ~" +
hours.toString().padStart(2, "0") +
":" +
minutes.toString().padStart(2, "0") +
"." +
seconds.toString().padStart(2, "0");
} else {
time_left =
"time left: ~" +
minutes.toString().padStart(2, "0") +
"." +
seconds.toString().padStart(2, "0");
}
}
var time_left = "" + time_left + " || Speed/min: ";
// SET BYTES PER MINUTE
if (typeof data.bytesperminute == "undefined") {
var arq_bytes_per_minute = 0;
} else {
var arq_bytes_per_minute = data.bytesperminute;
}
// SET BYTES PER MINUTE COMPRESSED
var compress = data.compression;
if (isNaN(compress)) {
compress = 1;
}
var arq_bytes_per_minute_compressed = Math.round(
arq_bytes_per_minute * compress,
);
time_left +=
formatBytes(arq_bytes_per_minute, 1) +
" (comp: " +
formatBytes(arq_bytes_per_minute_compressed, 1) +
")";
document.getElementById("transmission_timeleft").innerHTML = time_left;
connectedStation(data);
});
//Just some stuff I want to experiment with - n1qm
//https://gist.github.com/senseisimple/002cdba344de92748695a371cef0176a
function signal_quality_perc_quad(rssi, perfect_rssi = 10, worst_rssi = -150) {
nominal_rssi = perfect_rssi - worst_rssi;
signal_quality =
(100 * (perfect_rssi - worst_rssi) * (perfect_rssi - worst_rssi) -
(perfect_rssi - rssi) *
(15 * (perfect_rssi - worst_rssi) + 62 * (perfect_rssi - rssi))) /
((perfect_rssi - worst_rssi) * (perfect_rssi - worst_rssi));
if (signal_quality > 100) {
signal_quality = 100;
} else if (signal_quality < 1) {
signal_quality = 0;
}
return Math.ceil(signal_quality);
}
var lastHeard = "";
var checkForNewMessageWait = 85;
ipcRenderer.on("action-update-tnc-state", (event, arg) => {
//check for new messages
if (checkForNewMessageWait >= 100) {
//This is very expensive
ipcRenderer.send("request-update-unread-messages");
checkForNewMessageWait = -1;
}
checkForNewMessageWait++;
// update FFT only if data available
if (typeof arg.fft !== "undefined" && arg.fft !== "[]") {
try {
var array = JSON.parse("[" + arg.fft + "]");
spectrum.addData(array[0]);
} catch (e) {
console.log(e);
}
}
if (typeof arg.mycallsign !== "undefined") {
updateTitle(arg.mycallsign);
}
// update mygrid information with data from tnc
if (typeof arg.mygrid !== "undefined") {
document.getElementById("myGrid").value = arg.mygrid;
}
// DATA STATE
global.rxBufferLengthTnc = arg.rx_buffer_length;
// START OF SCATTER CHART
if (typeof arg.scatter == "undefined") {
var scatterSize = 0;
} else {
var scatterSize = arg.scatter.length;
}
if (scatterSize > 0 && global.scatterData != newScatterData) {
const scatterConfig = {
plugins: {
legend: {
display: false,
},
tooltip: {
enabled: false,
},
annotation: {
annotations: {
line1: {
type: "line",
yMin: 0,
yMax: 0,
borderColor: "rgb(255, 99, 132)",
borderWidth: 2,
},
line2: {
type: "line",
xMin: 0,
xMax: 0,
borderColor: "rgb(255, 99, 132)",
borderWidth: 2,
},
},
},
},
animations: false,
scales: {
x: {
type: "linear",
position: "bottom",
display: true,
min: -80,
max: 80,
ticks: {
display: false,
},
},
y: {
display: true,
min: -80,
max: 80,
ticks: {
display: false,
},
},
},
};
var scatterData = arg.scatter;
var newScatterData = {
datasets: [
{
//label: 'constellation diagram',
data: scatterData,
options: scatterConfig,
backgroundColor: "rgb(255, 99, 132)",
},
],
};
global.scatterData = newScatterData;
if (typeof global.scatterChart == "undefined") {
var scatterCtx = document.getElementById("scatter").getContext("2d");
global.scatterChart = new Chart(scatterCtx, {
type: "scatter",
data: global.scatterData,
options: scatterConfig,
});
} else {
global.scatterChart.data = global.scatterData;
global.scatterChart.update();
}
}
// END OF SCATTER CHART
// START OF SPEED CHART
var speedDataTime = [];
if (typeof arg.speed_list == "undefined") {
var speed_listSize = 0;
} else {
var speed_listSize = arg.speed_list.length;
}
for (var i = 0; i < speed_listSize; i++) {
var timestamp = arg.speed_list[i].timestamp * 1000;
var h = new Date(timestamp).getHours();
var m = new Date(timestamp).getMinutes();
var s = new Date(timestamp).getSeconds();
var time = h + ":" + m + ":" + s;
speedDataTime.push(time);
}
var speedDataBpm = [];
for (var i = 0; i < speed_listSize; i++) {
speedDataBpm.push(arg.speed_list[i].bpm);
}
var speedDataSnr = [];
for (var i = 0; i < speed_listSize; i++) {
let snr = NaN;
if (arg.speed_list[i].snr !== 0) {
snr = arg.speed_list[i].snr;
} else {
snr = NaN;
}
speedDataSnr.push(snr);
}
var speedChartConfig = {
type: "line",
};
// https://www.chartjs.org/docs/latest/samples/line/segments.html
const skipped = (speedCtx, value) =>
speedCtx.p0.skip || speedCtx.p1.skip ? value : undefined;
const down = (speedCtx, value) =>
speedCtx.p0.parsed.y > speedCtx.p1.parsed.y ? value : undefined;
var newSpeedData = {
labels: speedDataTime,
datasets: [
{
type: "line",
label: "SNR[dB]",
data: speedDataSnr,
borderColor: "rgb(75, 192, 192, 1.0)",
pointRadius: 1,
segment: {
borderColor: (speedCtx) =>
skipped(speedCtx, "rgb(0,0,0,0.4)") ||
down(speedCtx, "rgb(192,75,75)"),
borderDash: (speedCtx) => skipped(speedCtx, [3, 3]),
},
spanGaps: true,
backgroundColor: "rgba(75, 192, 192, 0.2)",
order: 1,
yAxisID: "SNR",
},
{
type: "bar",
label: "Speed[bpm]",
data: speedDataBpm,
borderColor: "rgb(120, 100, 120, 1.0)",
backgroundColor: "rgba(120, 100, 120, 0.2)",
order: 0,
yAxisID: "SPEED",
},
],
};
var speedChartOptions = {
responsive: true,
animations: true,
cubicInterpolationMode: "monotone",
tension: 0.4,
scales: {
SNR: {
type: "linear",
ticks: { beginAtZero: false, color: "rgb(255, 99, 132)" },
position: "right",
},
SPEED: {
type: "linear",
ticks: { beginAtZero: false, color: "rgb(120, 100, 120)" },
position: "left",
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
x: { ticks: { beginAtZero: true } },
},
};
if (typeof global.speedChart == "undefined") {
var speedCtx = document.getElementById("chart").getContext("2d");
global.speedChart = new Chart(speedCtx, {
data: newSpeedData,
options: speedChartOptions,
});
} else {
if (speedDataSnr.length > 0) {
global.speedChart.data = newSpeedData;
global.speedChart.update();
}
}
// END OF SPEED CHART
// PTT STATE
switch (arg.ptt_state) {
case "True":
document.getElementById("ptt_state").className =
"btn btn-sm btn-danger me-1";
break;
case "False":
document.getElementById("ptt_state").className =
"btn btn-sm btn-success me-1";
break;
default:
document.getElementById("ptt_state").className =
"btn btn-sm btn-secondary me-1";
break;
}
// AUDIO RECORDING
if (arg.audio_recording == "True") {
document.getElementById("startStopRecording").textContent = "Stop Rec";
} else {
document.getElementById("startStopRecording").textContent = "Record";
}
//CHANNEL CODEC2 BUSY STATE
if (arg.is_codec2_traffic == "True") {
document.getElementById("c2_busy").className = "btn btn-sm btn-success";
} else {
document.getElementById("c2_busy").className =
"btn btn-sm btn-outline-secondary";
}
// CHANNEL BUSY STATE
switch (arg.channel_busy) {
case "True":
document.getElementById("channel_busy").className =
"btn btn-sm btn-danger";
break;
case "False":
document.getElementById("channel_busy").className =
"btn btn-sm btn-success";
break;
default:
document.getElementById("channel_busy").className =
"btn btn-sm btn-secondary";
break;
}
// BUSY STATE
switch (arg.busy_state) {
case "BUSY":
document.getElementById("busy_state").className =
"btn btn-sm btn-danger me-1";
//Seems to be no longer user accessible
//document.getElementById("startTransmission").disabled = true;
break;
case "IDLE":
document.getElementById("busy_state").className =
"btn btn-sm btn-success me-1";
break;
default:
document.getElementById("busy_state").className =
"btn btn-sm btn-secondary me-1";
//Seems to be no longer user accessible
//document.getElementById("startTransmission").disabled = true;
break;
}
// ARQ STATE
switch (arg.arq_state) {
case "True":
document.getElementById("arq_state").className =
"btn btn-sm btn-warning me-1";
//Seems to be no longer user accessible
//document.getElementById("startTransmission").disabled = false;
break;
default:
document.getElementById("arq_state").className =
"btn btn-sm btn-secondary me-1";
//Seems to be no longer user accessible
//document.getElementById("startTransmission").disabled = false;
break;
}
// ARQ SESSION
switch (arg.arq_session) {
case "True":
document.getElementById("arq_session").className =
"btn btn-sm btn-warning me-1";
break;
default:
document.getElementById("arq_session").className =
"btn btn-sm btn-secondary me-1";
break;
}
if (arg.arq_state == "True" || arg.arq_session == "True") {
document.getElementById("spnConnectedWith").className =
"bi bi-chat-fill text-success me-1";
} else {
document.getElementById("spnConnectedWith").className = "bi bi-chat-fill";
ipcRenderer.send("request-clear-chat-connected");
}
// HAMLIB STATUS
if (arg.hamlib_status == "connected") {
document.getElementById("rigctld_state").className =
"btn btn-success btn-sm me-1";
} else {
document.getElementById("rigctld_state").className =
"btn btn-secondary btn-sm me-1";
}
// BEACON
switch (arg.beacon_state) {
case "True":
document.getElementById("startBeacon").className =
"btn btn-sm btn-success ms-1";
if (document.getElementById("beaconInterval").disabled == false) {
document.getElementById("beaconInterval").disabled = true;
}
break;
default:
document.getElementById("startBeacon").className =
"btn btn-sm btn-outline-secondary ms-1";
if (document.getElementById("beaconInterval").disabled == true) {
document.getElementById("beaconInterval").disabled = false;
}
break;
}
// dbfs
// https://www.moellerstudios.org/converting-amplitude-representations/
if (
arg.dbfs_level.length != 0 &&
!isNaN(arg.dbfs_level) &&
dbfs_level_raw != arg.dbfs_level
) {
dbfs_level_raw = arg.dbfs_level;
dbfs_level = Math.pow(10, arg.dbfs_level / 20) * 100;
document.getElementById("dbfs_level_value").textContent =
Math.round(arg.dbfs_level) + " dBFS (Audio Level)";
var dbfscntrl = document.getElementById("dbfs_level");
dbfscntrl.setAttribute("aria-valuenow", dbfs_level);
dbfscntrl.style = "width:" + dbfs_level + "%;";
//dbfscntrl.setAttribute("style", "width:" + dbfs_level + "%;");
}
// noise / strength
// https://www.moellerstudios.org/converting-amplitude-representations/
if (
arg.strength != 0 &&
!isNaN(arg.strength) &&
noise_level_raw != arg.strength
) {
//console.log(arg.strength);
noise_level_raw = arg.strength;
noise_level = Math.pow(10, arg.strength / 20) * 100;
document.getElementById("noise_level_value").textContent =
Math.round(arg.strength) + " dB (S-Meter)";
var noisecntrl = document.getElementById("noise_level");
noisecntrl.setAttribute("aria-valuenow", noise_level);
noisecntrl.style = "width:" + noise_level + "%;";
//noisecntrl.setAttribute("style", "width:" + noise_level + "%;");
}
// SET FREQUENCY
// https://stackoverflow.com/a/2901298
var freq = arg.frequency.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
document.getElementById("frequency").textContent = freq;
//document.getElementById("newFrequency").value = arg.frequency;
// SET MODE
document.getElementById("mode").textContent = arg.mode;
// SET bandwidth
document.getElementById("bandwidth").textContent = arg.bandwidth;
// SET SPEED LEVEL
switch (arg.speed_level) {
case "0":
document.getElementById("speed_level").className = "bi bi-reception-1";
break;
case "1":
document.getElementById("speed_level").className = "bi bi-reception-2";
break;
case "2":
document.getElementById("speed_level").className = "bi bi-reception-3";
break;
default:
document.getElementById("speed_level").className = "bi bi-reception-4";
break;
}
// SET TOTAL BYTES
if (typeof arg.total_bytes == "undefined") {
var total_bytes = 0;
} else {
var total_bytes = arg.total_bytes;
}
document.getElementById("total_bytes").textContent = total_bytes;
//Check if heard station list has changed
if (
typeof arg.stations != "undefined" &&
arg.stations.length > 0 &&
JSON.stringify(arg.stations) != lastHeard
) {
//console.log("Updating last heard stations");
lastHeard = JSON.stringify(arg.stations);
updateHeardStations(arg);
}
});
function updateHeardStations(arg) {
// UPDATE HEARD STATIONS
var tbl = document.getElementById("heardstations");
tbl.innerHTML = "";
if (typeof arg.stations == "undefined") {
var heardStationsLength = 0;
} else {
var heardStationsLength = arg.stations.length;
}
for (i = 0; i < heardStationsLength; i++) {
// first we update the PING window
if (
arg.stations[i]["dxcallsign"] ==
document.getElementById("dxCall").value.toUpperCase()
) {
var dxGrid = arg.stations[i]["dxgrid"];
var myGrid = document.getElementById("myGrid").value;
try {
var dist = parseInt(distance(myGrid, dxGrid)) + " km";
document.getElementById("dataModalPingDistance").textContent = dist;
} catch {
document.getElementById("dataModalPingDistance").textContent = "---";
}
document.getElementById("dataModalPingDB").textContent =
arg.stations[i]["snr"];
}
// now we update the heard stations list
var row = document.createElement("tr");
//https://stackoverflow.com/q/51421470
//https://stackoverflow.com/a/847196
timestampRaw = arg.stations[i]["timestamp"];
var datetime = new Date(timestampRaw * 1000).toLocaleString(
navigator.language,
{
hourCycle: "h23",
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
},
);
//var hours = date.getHours();
//var minutes = "0" + date.getMinutes();
//var seconds = "0" + date.getSeconds();
//var datetime = hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2);
var timestamp = document.createElement("td");
var timestampText = document.createElement("span");
timestampText.innerText = datetime;
timestamp.appendChild(timestampText);
var frequency = document.createElement("td");
var frequencyText = document.createElement("span");
frequencyText.innerText = arg.stations[i]["frequency"];
frequency.appendChild(frequencyText);
var dxCall = document.createElement("td");
var dxCallText = document.createElement("span");
dxCallText.innerText = arg.stations[i]["dxcallsign"];
let dxCallTextCall = dxCallText.innerText;
let dxCallTextShort = dxCallTextCall.split("-", 1)[0];
row.addEventListener("click", function () {
document.getElementById("dxCall").value = dxCallTextCall;
});
dxCall.appendChild(dxCallText);
var dxGrid = document.createElement("td");
var dxGridText = document.createElement("span");
dxGridText.innerText = arg.stations[i]["dxgrid"];
dxGrid.appendChild(dxGridText);
var gridDistance = document.createElement("td");
var gridDistanceText = document.createElement("span");
try {
if (arg.stations[i]["dxgrid"].toString() != "------") {
gridDistanceText.innerText =
parseInt(
distance(
document.getElementById("myGrid").value,
arg.stations[i]["dxgrid"],
),
) + " km";
} else {
gridDistanceText.innerText = "---";
}
} catch {
gridDistanceText.innerText = "---";
}
gridDistance.appendChild(gridDistanceText);
var dataType = document.createElement("td");
var dataTypeText = document.createElement("span");
dataTypeText.innerText = arg.stations[i]["datatype"];
dataType.appendChild(dataTypeText);
switch (dataTypeText.innerText) {
case "CQ CQ CQ":
dataTypeText.textContent = "CQ CQ";
row.classList.add("table-success");
break;
case "DATA-CHANNEL":
dataTypeText.innerHTML =
'';
row.classList.add("table-warning");
break;
case "BEACON":
dataTypeText.textContent = "BCN";
row.classList.add("table-light");
break;
case "PING":
row.classList.add("table-info");
break;
case "PING-ACK":
row.classList.add("table-primary");
break;
case "SESSION-HB":
dataTypeText.innerHTML =
'';
//dataType.appendChild(dataTypeText);
break;
}
var snr = document.createElement("td");
var snrText = document.createElement("span");
snrText.innerText = arg.stations[i]["snr"];
snr.appendChild(snrText);
var offset = document.createElement("td");
var offsetText = " ";
if (contrib.indexOf(dxCallTextShort) >= 0) {
var offsetText =
'';
} else {
if (dxCallTextShort == "DJ2LS") {
var offsetText =
'';
}
}
offset.innerHTML = offsetText;
row.appendChild(timestamp);
row.appendChild(frequency);
row.appendChild(offset);
row.appendChild(dxCall);
row.appendChild(dxGrid);
row.appendChild(gridDistance);
row.appendChild(dataType);
row.appendChild(snr);
tbl.appendChild(row);
}
sorthslTable(hslLastSort);
}
var populateSerial = false;
ipcRenderer.on("action-update-daemon-state", (event, arg) => {
/*
// deactivetd RAM und CPU view so we dont get errors. We need to find a new place for this feature
// RAM
document.getElementById("progressbar_ram").setAttribute("aria-valuenow", arg.ram_usage)
document.getElementById("progressbar_ram").setAttribute("style", "width:" + arg.ram_usage + "%;")
document.getElementById("progressbar_ram_value").innerHTML = arg.ram_usage + "%"
// CPU
document.getElementById("progressbar_cpu").setAttribute("aria-valuenow", arg.cpu_usage)
document.getElementById("progressbar_cpu").setAttribute("style", "width:" + arg.cpu_usage + "%;")
document.getElementById("progressbar_cpu_value").innerHTML = arg.cpu_usage + "%"
*/
/*
document.getElementById("ram_load").innerHTML = arg.ram_usage + "%"
document.getElementById("cpu_load").innerHTML = arg.cpu_usage + "%"
*/
// OPERATING SYSTEM
//document.getElementById("operating_system").innerHTML = "OS " + os.type()
/*
// PYTHON VERSION
document.getElementById("python_version").innerHTML = "Python " + arg.python_version
document.getElementById("python_version").className = "btn btn-sm btn-success";
*/
/*
// HAMLIB VERSION
document.getElementById("hamlib_version").innerHTML = "Hamlib " + arg.hamlib_version
document.getElementById("hamlib_version").className = "btn btn-sm btn-success";
*/
/*
// NODE VERSION
document.getElementById("node_version").innerHTML = "Node " + process.version
document.getElementById("node_version").className = "btn btn-sm btn-success";
*/
if (arg.tnc_running_state != "stopped" && populateSerial == true) return;
// UPDATE SERIAL DEVICES
if (
document.getElementById("hamlib_deviceport").length !=
arg.serial_devices.length
) {
document.getElementById("hamlib_deviceport").innerHTML = "";
var ignore = document.createElement("option");
ignore.text = "-- ignore --";
ignore.value = "ignore";
document.getElementById("hamlib_deviceport").add(ignore);
for (i = 0; i < arg.serial_devices.length; i++) {
var option = document.createElement("option");
option.text =
arg.serial_devices[i]["port"] +
" -- " +
arg.serial_devices[i]["description"];
option.value = arg.serial_devices[i]["port"];
document.getElementById("hamlib_deviceport").add(option);
}
// set device from config if available
document.getElementById("hamlib_deviceport").value =
config.hamlib_deviceport;
}
if (
document.getElementById("hamlib_ptt_port").length !=
arg.serial_devices.length
) {
document.getElementById("hamlib_ptt_port").innerHTML = "";
var ignore = document.createElement("option");
ignore.text = "-- ignore --";
ignore.value = "ignore";
document.getElementById("hamlib_ptt_port").add(ignore);
for (i = 0; i < arg.serial_devices.length; i++) {
var option = document.createElement("option");
option.text =
arg.serial_devices[i]["port"] +
" -- " +
arg.serial_devices[i]["description"];
option.value = arg.serial_devices[i]["port"];
document.getElementById("hamlib_ptt_port").add(option);
}
// set device from config if available
document.getElementById("hamlib_ptt_port").value = config.hamlib_ptt_port;
}
//Serial devices are updated on first pass
populateSerial = true;
if (arg.tnc_running_state != "stopped") return;
// UPDATE AUDIO INPUT
if (
document.getElementById("audio_input_selectbox").length !=
arg.input_devices.length
) {
document.getElementById("audio_input_selectbox").innerHTML = "";
for (i = 0; i < arg.input_devices.length; i++) {
var option = document.createElement("option");
option.text = arg.input_devices[i]["name"];
option.value = arg.input_devices[i]["id"];
// set device from config if available
if (config.rx_audio == option.text) {
option.setAttribute("selected", true);
}
document.getElementById("audio_input_selectbox").add(option);
}
}
// UPDATE AUDIO OUTPUT
if (
document.getElementById("audio_output_selectbox").length !=
arg.output_devices.length
) {
document.getElementById("audio_output_selectbox").innerHTML = "";
for (i = 0; i < arg.output_devices.length; i++) {
var option = document.createElement("option");
option.text = arg.output_devices[i]["name"];
option.value = arg.output_devices[i]["id"];
// set device from config if available
if (config.tx_audio == option.text) {
option.setAttribute("selected", true);
}
document.getElementById("audio_output_selectbox").add(option);
}
}
//Once audio devices are populated, try starting TNC if it hasn't been started yet in this session
//and if autostart is enabled
if (tncStartCount <= 0) autostart_tnc();
});
// ACTION UPDATE HAMLIB TEST
ipcRenderer.on("action-update-hamlib-test", (event, arg) => {
console.log(arg.hamlib_result);
if (arg.hamlib_result == "SUCCESS") {
document.getElementById("testHamlib").className = "btn btn-sm btn-success";
// BUTTON HAS BEEN REMOVED
//document.getElementById("testHamlibAdvanced").className = "btn btn-sm btn-success";
}
if (arg.hamlib_result == "NOSUCCESS") {
document.getElementById("testHamlib").className = "btn btn-sm btn-warning";
// BUTTON HAS BEEN REMOVED
//document.getElementById("testHamlibAdvanced").className = "btn btn-sm btn-warning";
}
if (arg.hamlib_result == "FAILED") {
document.getElementById("testHamlib").className = "btn btn-sm btn-danger";
// BUTTON HAS BEEN REMOVED
//document.getElementById("testHamlibAdvanced").className = "btn btn-sm btn-danger";
}
});
ipcRenderer.on("action-update-daemon-connection", (event, arg) => {
if (arg.daemon_connection == "open") {
document.getElementById("daemon_connection_state").className =
"btn btn-success";
//document.getElementById("blurdiv").style.webkitFilter = "blur(0px)";
}
if (arg.daemon_connection == "opening") {
document.getElementById("daemon_connection_state").className =
"btn btn-warning";
//document.getElementById("blurdiv").style.webkitFilter = "blur(10px)";
}
if (arg.daemon_connection == "closed") {
document.getElementById("daemon_connection_state").className =
"btn btn-danger";
//document.getElementById("blurdiv").style.webkitFilter = "blur(10px)";
}
});
ipcRenderer.on("action-update-tnc-connection", (event, arg) => {
if (arg.tnc_connection == "open") {
/*
document.getElementById('hamlib_deviceid').disabled = true;
document.getElementById('hamlib_deviceport').disabled = true;
document.getElementById('testHamlib').disabled = true;
document.getElementById('hamlib_ptt_protocol').disabled = true;
document.getElementById('audio_input_selectbox').disabled = true;
document.getElementById('audio_output_selectbox').disabled = true;
//document.getElementById('stopTNC').disabled = false;
document.getElementById('startTNC').disabled = true;
document.getElementById('dxCall').disabled = false;
document.getElementById("hamlib_serialspeed").disabled = true;
document.getElementById("openDataModule").disabled = false;
*/
// collapse settings screen
var collapseFirstRow = new bootstrap.Collapse(
document.getElementById("collapseFirstRow"),
{ toggle: false },
);
collapseFirstRow.hide();
var collapseSecondRow = new bootstrap.Collapse(
document.getElementById("collapseSecondRow"),
{ toggle: false },
);
collapseSecondRow.hide();
var collapseThirdRow = new bootstrap.Collapse(
document.getElementById("collapseThirdRow"),
{ toggle: false },
);
collapseThirdRow.show();
var collapseFourthRow = new bootstrap.Collapse(
document.getElementById("collapseFourthRow"),
{ toggle: false },
);
collapseFourthRow.show();
//Set tuning for fancy graphics mode (high/low CPU)
set_CPU_mode();
//GUI will auto connect to TNC if already running, if that is the case increment start count if 0
if (tncStartCount == 0) tncStartCount++;
} else {
/*
document.getElementById('hamlib_deviceid').disabled = false;
document.getElementById('hamlib_deviceport').disabled = false;
document.getElementById('testHamlib').disabled = false;
document.getElementById('hamlib_ptt_protocol').disabled = false;
document.getElementById('audio_input_selectbox').disabled = false;
document.getElementById('audio_output_selectbox').disabled = false;
//document.getElementById('stopTNC').disabled = true;
document.getElementById('startTNC').disabled = false;
document.getElementById('dxCall').disabled = true;
document.getElementById("hamlib_serialspeed").disabled = false;
document.getElementById("openDataModule").disabled = true;
*/
// collapse settings screen
var collapseFirstRow = new bootstrap.Collapse(
document.getElementById("collapseFirstRow"),
{ toggle: false },
);
collapseFirstRow.show();
var collapseSecondRow = new bootstrap.Collapse(
document.getElementById("collapseSecondRow"),
{ toggle: false },
);
collapseSecondRow.show();
var collapseThirdRow = new bootstrap.Collapse(
document.getElementById("collapseThirdRow"),
{ toggle: false },
);
collapseThirdRow.hide();
var collapseFourthRow = new bootstrap.Collapse(
document.getElementById("collapseFourthRow"),
{ toggle: false },
);
collapseFourthRow.hide();
}
});
ipcRenderer.on("action-update-rx-buffer", (event, arg) => {
var data = arg.data["data"];
var tbl = document.getElementById("rx-data");
document.getElementById("rx-data").innerHTML = "";
for (i = 0; i < arg.data.length; i++) {
// first we update the PING window
if (
arg.data[i]["dxcallsign"] ==
document.getElementById("dxCall").value.toUpperCase()
) {
/*
// if we are sending data without doing a ping before, we don't have a grid locator available. This could be a future feature for the TNC!
if(arg.data[i]['DXGRID'] != ''){
document.getElementById("pingDistance").innerHTML = arg.stations[i]['DXGRID']
}
*/
//document.getElementById("pingDB").innerHTML = arg.stations[i]['snr'];
document.getElementById("dataModalPingDB").innerHTML =
arg.stations[i]["snr"];
}
// now we update the received files list
var row = document.createElement("tr");
//https://stackoverflow.com/q/51421470
//https://stackoverflow.com/a/847196
timestampRaw = arg.data[i]["timestamp"];
var date = new Date(timestampRaw * 1000);
var hours = date.getHours();
var minutes = "0" + date.getMinutes();
var seconds = "0" + date.getSeconds();
var datetime = hours + ":" + minutes.substr(-2) + ":" + seconds.substr(-2);
var timestamp = document.createElement("td");
var timestampText = document.createElement("span");
timestampText.innerText = datetime;
timestamp.appendChild(timestampText);
var dxCall = document.createElement("td");
var dxCallText = document.createElement("span");
dxCallText.innerText = arg.data[i]["dxcallsign"];
dxCall.appendChild(dxCallText);
/*
var dxGrid = document.createElement("td");
var dxGridText = document.createElement('span');
dxGridText.innerText = arg.data[i]['DXGRID']
dxGrid.appendChild(dxGridText);
*/
console.log(arg.data);
var encoded_data = FD.atob_FD(arg.data[i]["data"]);
var splitted_data = encoded_data.split(split_char);
console.log(splitted_data);
var fileName = document.createElement("td");
var fileNameText = document.createElement("span");
//var fileNameString = arg.data[i]['data'][0]['fn'];
var fileNameString = splitted_data[1];
fileNameText.innerText = fileNameString;
fileName.appendChild(fileNameText);
row.appendChild(timestamp);
row.appendChild(dxCall);
// row.appendChild(dxGrid);
row.appendChild(fileName);
tbl.appendChild(row);
// https://stackoverflow.com/a/26227660
//var appDataFolder = process.env.HOME;
//console.log("appDataFolder:" + appDataFolder);
//var applicationFolder = path.join(appDataFolder, "FreeDATA");
//console.log(applicationFolder);
//var receivedFilesFolder = path.join(applicationFolder, "receivedFiles");
var receivedFilesFolder = path.join(config.received_files_folder);
console.log("receivedFilesFolder: " + receivedFilesFolder);
// Creates receivedFiles folder if not exists
// https://stackoverflow.com/a/13544465
fs.mkdir(
receivedFilesFolder,
{
recursive: true,
},
function (err) {
console.log(err);
},
);
// write file to data folder
////var base64String = arg.data[i]['data'][0]['d']
// remove header from base64 String
// https://www.codeblocq.com/2016/04/Convert-a-base64-string-to-a-file-in-Node/
////var base64Data = base64String.split(';base64,').pop()
//write data to file
var base64Data = splitted_data[4];
var receivedFile = path.join(receivedFilesFolder, fileNameString);
console.log(receivedFile);
require("fs").writeFile(receivedFile, base64Data, "binary", function (err) {
//require("fs").writeFile(receivedFile, base64Data, 'base64', function(err) {
console.log(err);
});
}
});
ipcRenderer.on("run-tnc-command-fec-iswriting", (event) => {
//console.log("Sending sendFecIsWriting");
sock.sendFecIsWriting(config.mycall);
});
//Change background color of RF Chat button if new messages are available
ipcRenderer.on("action-update-unread-messages-main", (event, data) => {
//Do something
if (data == true) {
document.getElementById("list-messages-list").classList.add("bg-warning");
document.getElementById("list-messages-list").classList.remove("bg-secondary");
} else {
document.getElementById("list-messages-list").classList.remove("bg-warning");
document.getElementById("list-messages-list").classList.add("bg-secondary");
}
});
ipcRenderer.on("run-tnc-command", (event, arg) => {
if (arg.command == "save_my_call") {
sock.saveMyCall(arg.callsign);
}
if (arg.command == "save_my_grid") {
sock.saveMyGrid(arg.grid);
}
if (arg.command == "ping") {
sock.sendPing(arg.dxcallsign);
}
if (arg.command == "send_file") {
sock.sendFile(
arg.dxcallsign,
arg.mode,
arg.frames,
arg.filename,
arg.filetype,
arg.data,
arg.checksum,
);
}
if (arg.command == "msg") {
sock.sendMessage(
arg.dxcallsign,
arg.mode,
arg.frames,
arg.data,
arg.checksum,
arg.uuid,
arg.command,
);
}
if (arg.command == "broadcast") {
sock.sendBroadcastChannel(arg.broadcastChannel, arg.data, arg.uuid);
}
if (arg.command == "stop_transmission") {
sock.stopTransmission();
}
if (arg.command == "set_tx_audio_level") {
sock.setTxAudioLevel(arg.tx_audio_level);
}
if (arg.command == "record_audio") {
sock.record_audio();
}
if (arg.command == "send_test_frame") {
sock.sendTestFrame();
}
if (arg.command == "frequency") {
sock.set_frequency(arg.frequency);
}
if (arg.command == "mode") {
sock.set_mode(arg.mode);
}
if (arg.command == "requestUserInfo") {
sock.sendRequestInfo(arg.dxcallsign);
}
if (arg.command == "requestSharedFolderList") {
sock.sendRequestSharedFolderList(arg.dxcallsign);
}
if (arg.command == "requestSharedFile") {
sock.sendRequestSharedFile(arg.dxcallsign, arg.file);
}
// responses
if (arg.command == "responseUserInfo") {
sock.sendResponseInfo(arg.dxcallsign, arg.userinfo);
}
if (arg.command == "responseSharedFolderList") {
sock.sendResponseSharedFolderList(arg.dxcallsign, arg.folderFileList);
}
if (arg.command == "responseSharedFile") {
sock.sendResponseSharedFile(arg.dxcallsign, arg.file, arg.filedata);
}
if (arg.command == "mesh_ping") {
sock.sendMeshPing(arg.dxcallsign);
}
});
// IPC ACTION FOR AUTO UPDATER
ipcRenderer.on("action-updater", (event, arg) => {
if (arg.status == "download-progress") {
var progressinfo =
"(" +
Math.round(arg.progress.transferred / 1024) +
"kB /" +
Math.round(arg.progress.total / 1024) +
"kB)" +
" @ " +
Math.round(arg.progress.bytesPerSecond / 1024) +
"kByte/s";
document.getElementById("UpdateProgressInfo").innerHTML = progressinfo;
document
.getElementById("UpdateProgressBar")
.setAttribute("aria-valuenow", arg.progress.percent);
document
.getElementById("UpdateProgressBar")
.setAttribute("style", "width:" + arg.progress.percent + "%;");
}
if (arg.status == "checking-for-update") {
//document.title = document.title + ' - v' + arg.version;
updateTitle(
config.myCall,
config.tnc_host,
config.tnc_port,
" -v " + arg.version,
);
document.getElementById("updater_status").innerHTML =
'';
document.getElementById("updater_status").className =
"btn btn-secondary btn-sm";
document.getElementById("update_and_install").style.display = "none";
}
if (arg.status == "update-downloaded") {
document.getElementById("update_and_install").removeAttribute("style");
document.getElementById("updater_status").innerHTML =
'';
document.getElementById("updater_status").className =
"btn btn-success btn-sm";
// HERE WE NEED TO RUN THIS SOMEHOW...
//mainLog.info('quit application and install update');
//autoUpdater.quitAndInstall();
}
if (arg.status == "update-not-available") {
document.getElementById("updater_status").innerHTML =
'';
document.getElementById("updater_status").className =
"btn btn-success btn-sm";
document.getElementById("update_and_install").style.display = "none";
}
if (arg.status == "update-available") {
document.getElementById("updater_status").innerHTML =
'';
document.getElementById("updater_status").className =
"btn btn-warning btn-sm";
document.getElementById("update_and_install").style.display = "none";
}
if (arg.status == "error") {
document.getElementById("updater_status").innerHTML =
'';
document.getElementById("updater_status").className =
"btn btn-danger btn-sm";
document.getElementById("update_and_install").style.display = "none";
}
});
// ----------- INFO MODAL ACTIONS -------------------------------
// CQ TRANSMITTING
ipcRenderer.on("action-show-cq-toast-transmitting", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = "transmitting cq"),
(duration = 5000),
);
});
// fec iswriting received
ipcRenderer.on("action-show-fec-toast-iswriting", (event, data) => {
let dxcallsign = data["data"][0]["dxcallsign"];
let content = `${dxcallsign} is typing`;
displayToast(
(type = "success"),
(icon = "bi-pencil-fill"),
(content = content),
(duration = 5000),
);
});
// CQ RECEIVED
ipcRenderer.on("action-show-cq-toast-received", (event, data) => {
let dxcallsign = data["data"][0]["dxcallsign"];
let dxgrid = data["data"][0]["dxgrid"];
let content = `cq from ${dxcallsign} (${dxgrid})`;
showOsPopUp("CQ from " + dxcallsign, "Say hello!");
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = content),
(duration = 5000),
);
});
// QRV TRANSMITTING
ipcRenderer.on("action-show-qrv-toast-transmitting", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = "transmitting qrv"),
(duration = 5000),
);
});
// QRV RECEIVED
ipcRenderer.on("action-show-qrv-toast-received", (event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let dxgrid = data["data"][0]["dxgrid"];
let content = `received qrv from ${dxcallsign} (${dxgrid})`;
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = content),
(duration = 5000),
);
});
// BEACON TRANSMITTING
ipcRenderer.on("action-show-beacon-toast-transmitting", (event, data) => {
displayToast(
(type = "info"),
(icon = "bi-broadcast"),
(content = "transmitting beacon"),
(duration = 5000),
);
});
// BEACON RECEIVED
ipcRenderer.on("action-show-beacon-toast-received", (event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let dxgrid = data["data"][0]["dxgrid"];
let content = `beacon from ${dxcallsign} (${dxgrid})`;
displayToast(
(type = "info"),
(icon = "bi-broadcast"),
(content = content),
(duration = 5000),
);
});
// PING TRANSMITTING
ipcRenderer.on("action-show-ping-toast-transmitting", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = "transmitting ping"),
(duration = 5000),
);
});
// PING RECEIVED
ipcRenderer.on("action-show-ping-toast-received", (event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let content = `ping from ${dxcallsign}`;
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = content),
(duration = 5000),
);
});
// PING RECEIVED ACK
ipcRenderer.on("action-show-ping-toast-received-ack", (event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let dxgrid = data["data"][0]["dxgrid"];
let content = `ping ACK from ${dxcallsign} (${dxgrid})`;
displayToast(
(type = "success"),
(icon = "bi-check"),
(content = content),
(duration = 5000),
);
});
// DATA CHANNEL OPENING TOAST
ipcRenderer.on("action-show-arq-toast-datachannel-opening", (event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let content = `opening datachannel with ${dxcallsign}`;
displayToast(
(type = "secondary"),
(icon = "bi-arrow-left-right"),
(content = content),
(duration = 5000),
);
});
// DATA CHANNEL WAITING TOAST
ipcRenderer.on("action-show-arq-toast-datachannel-waiting", (event, data) => {
displayToast(
(type = "warning"),
(icon = "bi-smartwatch"),
(content = "channel busy - waiting..."),
(duration = 5000),
);
});
// DATA CHANNEL OPEN TOAST
ipcRenderer.on("action-show-arq-toast-datachannel-open", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-arrow-left-right"),
(content = "datachannel open"),
(duration = 5000),
);
});
// DATA CHANNEL RECEIVED OPENER TOAST
ipcRenderer.on(
"action-show-arq-toast-datachannel-received-opener",
(event, data) => {
console.log(data["data"][0]);
let dxcallsign = data["data"][0]["dxcallsign"];
let content = `datachannel requested by ${dxcallsign}`;
displayToast(
(type = "success"),
(icon = "bi-arrow-left-right"),
(content = content),
(duration = 5000),
);
},
);
// ARQ TRANSMISSION FAILED
// TODO: use for both - transmitting and receiving --> we need to change the IDs
ipcRenderer.on("action-show-arq-toast-transmission-failed", (event, data) => {
displayToast(
(type = "danger"),
(icon = "bi-arrow-left-right"),
(content = "transmission failed"),
(duration = 5000),
);
});
// ARQ TRANSMISSION FAILED (Version mismatch)
ipcRenderer.on(
"action-show-arq-toast-transmission-failed-ver",
(event, data) => {
displayToast(
(type = "danger"),
(icon = "bi-broadcast"),
(content = "protocol version missmatch"),
(duration = 5000),
);
},
);
// ARQ TRANSMISSION STOPPED
// TODO: RENAME ID -- WRONG
ipcRenderer.on("action-show-arq-toast-transmission-stopped", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-arrow-left-right"),
(content = "transmission stopped"),
(duration = 5000),
);
});
// ARQ TRANSMISSION FAILED
// TODO: USE FOR TX AND RX
ipcRenderer.on("action-show-arq-toast-transmission-failed", (event, data) => {
displayToast(
(type = "danger"),
(icon = "bi-broadcast"),
(content = "arq transmission failed"),
(duration = 5000),
);
});
// ARQ TRANSMISSION TRANSMITTED
ipcRenderer.on(
"action-show-arq-toast-transmission-transmitted",
(event, data) => {
console.log(data["data"][0]);
//let content = `received cq from ${dxcallsign} (${dxgrid})`;
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = "data transmitted"),
(duration = 5000),
);
},
);
// ARQ TRANSMISSION TRANSMITTING
ipcRenderer.on(
"action-show-arq-toast-transmission-transmitting",
(event, data) => {
var irs_snr = data["data"][0].irs_snr;
if (irs_snr <= 0) {
displayToast(
(type = "warning"),
(icon = "bi-broadcast"),
(content = "low link margin: " + irs_snr + " dB"),
(duration = 5000),
);
} else if (irs_snr > 0 && irs_snr <= 5) {
displayToast(
(type = "warning"),
(icon = "bi-broadcast"),
(content = "medium link margin: " + irs_snr + " dB"),
(duration = 5000),
);
} else if (irs_snr > 5 && irs_snr < 12.7) {
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content = "high link margin: " + irs_snr + " dB"),
(duration = 5000),
);
} else if (irs_snr >= 12.7) {
displayToast(
(type = "success"),
(icon = "bi-broadcast"),
(content =
"very high link margin: " + irs_snr + " dB"),
(duration = 5000),
);
} else {
//displayToast(type='info', icon='bi-broadcast', content='no snr information', duration=5000);
}
},
);
// ARQ TRANSMISSION RECEIVED
ipcRenderer.on("action-show-arq-toast-transmission-received", (event, data) => {
console.log(data["data"][0]);
displayToast(
(type = "success"),
(icon = "bi-check-circle"),
(content = "all data received"),
(duration = 5000),
);
});
// ARQ TRANSMISSION RECEIVING
ipcRenderer.on(
"action-show-arq-toast-transmission-receiving",
(event, data) => {
displayToast(
(type = "primary"),
(icon = "bi-arrow-left-right"),
(content = "session receiving"),
(duration = 5000),
);
},
);
// ARQ SESSION CONNECTING
ipcRenderer.on("action-show-arq-toast-session-connecting", (event, data) => {
displayToast(
(type = "primary"),
(icon = "bi-arrow-left-right"),
(content = "connecting..."),
(duration = 5000),
);
});
// ARQ SESSION CONNECTED
ipcRenderer.on("action-show-arq-toast-session-connected", (event, data) => {
displayToast(
(type = "success"),
(icon = "bi-arrow-left-right"),
(content = "session connected"),
(duration = 5000),
);
});
// ARQ SESSION CONNECTED
ipcRenderer.on("action-show-arq-toast-session-waiting", (event, data) => {
displayToast(
(type = "warning"),
(icon = "bi-smartwatch"),
(content = "session waiting..."),
(duration = 5000),
);
});
// ARQ SESSION CLOSE
ipcRenderer.on("action-show-arq-toast-session-close", (event, data) => {
displayToast(
(type = "warning"),
(icon = "bi-arrow-left-right"),
(content = "session close"),
(duration = 5000),
);
});
// ARQ SESSION FAILED
ipcRenderer.on("action-show-arq-toast-session-failed", (event, data) => {
displayToast(
(type = "danger"),
(icon = "bi-arrow-left-right"),
(content = "session failed"),
(duration = 5000),
);
});
// enable or disable a setting by given switch and element
// not used at this time
function enable_setting(enable_switch, enable_object) {
if (document.getElementById(enable_switch).checked) {
config[enable_switch] = true;
document
.getElementById(enable_object)
.removeAttribute("disabled", "disabled");
} else {
config[enable_switch] = false;
document.getElementById(enable_object).setAttribute("disabled", "disabled");
}
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
}
// enable or disable a setting switch
// not used at this time
function set_setting_switch(setting_switch, enable_object, state) {
document.getElementById(setting_switch).checked = state;
enable_setting(setting_switch, enable_object);
}
var rigctldActive = false;
setInterval(checkRigctld, 500);
function checkRigctld() {
var rigctld_ip = document.getElementById("hamlib_rigctld_ip").value;
var rigctld_port = document.getElementById("hamlib_rigctld_port").value;
let Data = {
ip: rigctld_ip,
port: rigctld_port,
};
//Prevents an error on startup if hamlib settings aren't populated yet
if (rigctld_port.length > 0 && rigctld_ip.length > 0) {
ipcRenderer.send("request-check-rigctld", Data);
}
}
ipcRenderer.on("action-check-rigctld", (event, data) => {
document.getElementById("hamlib_rigctld_status").value = data["state"];
rigctldActive = data["active"];
if (data["active"] == true) {
document.getElementById("hamlib_rigctld_stop").disabled = false;
document.getElementById("hamlib_rigctld_start").disabled = true;
document.getElementById("testHamlib").disabled = false;
} else {
document.getElementById("hamlib_rigctld_stop").disabled = true;
document.getElementById("hamlib_rigctld_start").disabled = false;
document.getElementById("testHamlib").disabled = true;
}
});
ipcRenderer.on("action-set-app-version", (event, data) => {
appVer = data;
});
function updateTitle(
mycall = config.mycall,
tnc = config.tnc_host,
tncport = config.tnc_port,
appender = "",
) {
//Multiple consecutive spaces get converted to a single space
var title =
"FreeDATA " +
appVer +
" - Call: " +
mycall +
" - TNC: " +
tnc +
":" +
tncport +
appender;
if (title != document.title) {
document.title = title;
}
}
//Set force to true to ensure a class is present on a control, otherwise set to false to ensure it isn't present
function toggleClass(control, classToToggle, force) {
var cntrl = document.getElementById(control);
if (cntrl == undefined) {
console.log("toggle class: unknown control: ", control);
return;
}
var activeClasses = cntrl.className;
//var oldactive = activeClasses;
if (force == true && activeClasses.indexOf(classToToggle) >= 0) {
return;
}
if (force == false && activeClasses.indexOf(classToToggle) == -1) {
return;
}
if (force == true) {
activeClasses += " " + classToToggle;
} else {
activeClasses = activeClasses.replace(classToToggle, "");
}
activeClasses = activeClasses.replace(" ", " ").trim();
cntrl.className = activeClasses;
//console.log(control," toggleClass; force: ", force, "class: " ,classToToggle, " in: '" ,oldactive, "' out: '",activeClasses,"'");
}
function set_CPU_mode() {
if (config.high_graphics.toUpperCase() == "FALSE") {
toggleClass("dbfs_level", "disable-effects", true);
toggleClass("dbfs_level", "progress-bar-striped", false);
toggleClass("noise_level", "disable-effects", true);
toggleClass("noise_level", "progress-bar-striped", false);
toggleClass("waterfall", "disable-effects", true);
toggleClass("transmission_progress", "disable-effects", true);
toggleClass("transmission_progress", "progress-bar-striped", false);
} else {
toggleClass("dbfs_level", "disable-effects", false);
toggleClass("dbfs_level", "progress-bar-striped", true);
toggleClass("noise_level", "disable-effects", false);
toggleClass("noise_level", "progress-bar-striped", true);
toggleClass("waterfall", "disable-effects", false);
toggleClass("transmission_progress", "disable-effects", false);
toggleClass("transmission_progress", "progress-bar-striped", true);
}
}
//Temporarily disable a button with timeout
function pauseButton(btn, timems) {
btn.disabled = true;
var curText = btn.innerHTML;
if (config.high_graphics.toUpperCase() == "TRUE") {
btn.innerHTML =
'';
}
setTimeout(() => {
btn.innerHTML = curText;
btn.disabled = false;
}, timems);
}
//https://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-bytes-to-kb-mb-gb-in-javascript
function formatBytes(bytes, decimals = 1) {
if (!+bytes) return "0 Bytes";
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
// display toast
function displayToast(
type = "primary",
icon = "bi-info",
content = "default",
duration = 5000,
) {
mainToastContainer = document.getElementById("mainToastContainer");
let randomID = uuidv4();
let toastCode = `
`;
// insert toast to toast container
mainToastContainer.insertAdjacentHTML("beforeend", toastCode);
// register toast
let toastHTMLElement = document.getElementById(randomID);
let toast = bootstrap.Toast.getOrCreateInstance(toastHTMLElement); // Returns a Bootstrap toast instance
toast._config.delay = duration;
// show toast
toast.show();
//register event listener if toast is hidden
toastHTMLElement.addEventListener("hidden.bs.toast", () => {
// remove eventListener
toastHTMLElement.removeEventListener("hidden.bs.toast", this);
// remove toast
toastHTMLElement.remove();
});
}
function loadSettings(elements) {
elements.forEach(function (id) {
let element = document.getElementById(id);
if (element.tagName === "SELECT") {
element.value = config[id];
// add selected value
for (var i = 0, j = element.options.length; i < j; ++i) {
if (element.options[i].innerHTML === config[id]) {
element.selectedIndex = i;
break;
}
}
} else if (element.tagName === "INPUT" && element.type === "text") {
element.value = config[id];
} else if (element.tagName === "INPUT" && element.type === "radio") {
element.value = config[id];
if (config[id] === "True") {
element.checked = true;
} else {
element.checked = false;
}
} else {
console.log("nothing matched....");
}
});
ipcRenderer.on("update-config", (event, data) => {
config = data;
});
}
function changeGuiDesign(design) {
if (
design != "default" &&
design != "default_light" &&
design != "default_dark" &&
design != "default_auto"
) {
var theme_path =
"../node_modules/bootswatch/dist/" + design + "/bootstrap.min.css";
document.getElementById("theme_selector").value = design;
document.getElementById("bootstrap_theme").href = escape(theme_path);
} else if (design == "default" || design == "default_light") {
var theme_path = "../node_modules/bootstrap/dist/css/bootstrap.min.css";
document.getElementById("theme_selector").value = "default_light";
document.getElementById("bootstrap_theme").href = escape(theme_path);
document.documentElement.setAttribute("data-bs-theme", "light");
} else if (design == "default_dark") {
var theme_path = "../node_modules/bootstrap/dist/css/bootstrap.min.css";
document.getElementById("theme_selector").value = "default_dark";
document.getElementById("bootstrap_theme").href = escape(theme_path);
document.querySelector("html").setAttribute("data-bs-theme", "dark");
} else if (design == "default_auto") {
var theme_path = "../node_modules/bootstrap/dist/css/bootstrap.min.css";
document.getElementById("theme_selector").value = "default_auto";
document.getElementById("bootstrap_theme").href = escape(theme_path);
// https://stackoverflow.com/a/57795495
// check if dark mode or light mode used in OS
if (
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
// dark mode
document.documentElement.setAttribute("data-bs-theme", "dark");
} else {
document.documentElement.setAttribute("data-bs-theme", "light");
}
// also register event listener for automatic change
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (event) => {
let newColorScheme = event.matches ? "dark" : "light";
if (newColorScheme == "dark") {
document.documentElement.setAttribute("data-bs-theme", "dark");
} else {
document.documentElement.setAttribute("data-bs-theme", "light");
}
});
} else {
var theme_path = "../node_modules/bootstrap/dist/css/bootstrap.min.css";
document.getElementById("theme_selector").value = "default_light";
document.getElementById("bootstrap_theme").href = escape(theme_path);
document.documentElement.setAttribute("data-bs-theme", "light");
}
//update path to css file
document.getElementById("bootstrap_theme").href = escape(theme_path);
}
var hslLastSort = 0;
var hslLastSortDir = "desc";
//https://www.w3schools.com/howto/howto_js_sort_table.asp
function sorthslTable(n) {
hslLastSort = n;
var table,
rows,
switching,
i,
x,
y,
shouldSwitch,
dir,
switchcount = 0;
table = document.getElementById("tblHeardStationList");
switching = true;
// Set the sorting direction to ascending:
//hslLastSortDir = "asc";
/* Make a loop that will continue until
no switching has been done: */
while (switching) {
// Start by saying: no switching is done:
switching = false;
rows = table.rows;
/* Loop through all table rows (except the
first, which contains table headers): */
for (i = 1; i < rows.length - 1; i++) {
// Start by saying there should be no switching:
shouldSwitch = false;
/* Get the two elements you want to compare,
one from current row and one from the next: */
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
/* Check if the two rows should switch place,
based on the direction, asc or desc: */
if (hslLastSortDir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
// If so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
} else if (hslLastSortDir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
// If so, mark as a switch and break the loop:
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
/* If a switch has been marked, make the switch
and mark that a switch has been done: */
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
// Each time a switch is done, increase this count by 1:
switchcount++;
}
}
}
function autostart_rigctld() {
if (config.auto_start == 1) {
//Start rigctld if radiocontrol is in correct mode and is not active
if (config.radiocontrol == "rigctld" && rigctldActive == false) {
//console.log("Autostarting rigctld");
document.getElementById("hamlib_rigctld_start").click();
}
}
}
function autostart_tnc() {
if (config.auto_start == 1) {
//Now start TNC
document.getElementById("startTNC").click();
}
}
//Have the operating system show a notification popup
function showOsPopUp(title, message) {
if (config.enable_sys_notification == 0) return;
const NOTIFICATION_TITLE = title;
const NOTIFICATION_BODY = message;
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY });
}