Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 48 additions & 26 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,10 @@

#buttonsRow {
position: fixed;
bottom: 8px;
width: 100%;
padding: 10px;
bottom: 50px;
left: 0;
right: 0;
padding: 4px 0;
}

#reload_icon {
Expand Down Expand Up @@ -282,29 +283,14 @@
</div>
</div>
</div>
<div class="row" id="buttonsRow">
<div class="col">
<div class="mb-4 col-mb-4" style="text-align: left">
<button type="button" class="btn btn-primary" id="save">Save</button>
</div>
</div>
<div class="col">
<div class="mb-4 col-mb-4" style="text-align: left">
<button type="button" class="btn btn-primary" id="toggle" title="Manage profiles">
<span id="currentProfileName">Profile 1</span>
</button>
</div>
</div>
<div class="col">
<div class="mb-4 col-mb-4" style="text-align: center">
<button type="button" class="btn btn-primary" id="test">Test</button>
</div>
</div>
<div class="col">
<div class="mb-4 col-mb-4" style="text-align: right">
<button type="button" class="btn btn-primary" id="quit">Quit</button>
</div>
</div>
<div class="d-flex align-items-center justify-content-center" id="buttonsRow" style="gap: 12px;">
<button type="button" class="btn btn-primary" id="save" title="Save">💾</button>
<button type="button" class="btn btn-primary" id="toggle" title="Manage profiles">
<span id="currentProfileName">Profile 1</span>
</button>
<button type="button" class="btn btn-primary" id="test">Test</button>
<button type="button" class="btn btn-primary" id="advanced" title="Advanced">⚙️</button>
<button type="button" class="btn btn-primary" id="quit">Quit</button>
</div>

</div>
Expand All @@ -315,6 +301,42 @@
</div>
</div>

<!-- Advanced Settings Modal -->
<div class="modal fade" id="advancedModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Advanced Settings</h5>
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<!-- UDP Listener Settings -->
<h6>UDP Listener (WSJT-X)</h6>
<div class="form-group">
<div class="custom-control custom-switch mb-3">
<input type="checkbox" class="custom-control-input" id="udp_enabled">
<label class="custom-control-label" for="udp_enabled">Enable UDP Listener</label>
</div>
</div>
<div class="form-group">
<label for="udp_port">UDP Port</label>
<input type="number" class="form-control" id="udp_port" min="1024" max="65535" value="2333">
<small class="form-text text-muted">WSJT-X Secondary UDP Server port (default: 2333)</small>
</div>
<div class="alert alert-info mt-3" id="udp_status" style="display: none;">
<small id="udp_status_text"></small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" id="advancedCancel">Cancel</button>
<button type="button" class="btn btn-primary" id="advancedSave">Save</button>
</div>
</div>
</div>
</div>

<!-- Profile Manager Modal -->
<div class="modal fade" id="profileModal" tabindex="-1">
<div class="modal-dialog">
Expand Down
122 changes: 107 additions & 15 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ let msgbacklog=[];
let qsyServer; // Dual-mode HTTP/HTTPS server for QSY
let currentCAT=null;
var WServer;
let udpServer = null; // UDP server for ADIF/WSJT-X
let wsServer;
let wsClients = new Set();
let wssServer; // Secure WebSocket server
Expand Down Expand Up @@ -60,6 +61,8 @@ let defaultcfg = {
hamlib_port: '4532',
hamlib_ena: false,
ignore_pwr: false,
udp_enabled: true, // Global UDP setting (not per-profile)
udp_port: 2333, // Global UDP port (not per-profile)
}

const storage = require('electron-json-storage');
Expand Down Expand Up @@ -254,6 +257,20 @@ ipcMain.on("get_config", async (event, arg) => {
if (e) throw e;
});
}
// Migration: Add global UDP settings (version 3)
if (!realcfg.version || realcfg.version < 3) {
realcfg.version = 3;
// Add global UDP settings if not present
if (realcfg.udp_enabled === undefined) {
realcfg.udp_enabled = true;
}
if (realcfg.udp_port === undefined) {
realcfg.udp_port = 2333;
}
storage.set('basic', realcfg, function(e) {
if (e) throw e;
});
}
if ((arg ?? '') !== '') {
realcfg.profile=arg;
}
Expand Down Expand Up @@ -318,6 +335,21 @@ ipcMain.on("check_for_updates", async (event) => {
event.returnValue = true;
});

ipcMain.on("restart_udp", async (event) => {
// Restart UDP server with current configuration
startUdpServer();
event.returnValue = true;
});

ipcMain.on("get_udp_status", async (event) => {
// Return current UDP server status (global settings)
event.returnValue = {
enabled: defaultcfg.udp_enabled !== undefined ? defaultcfg.udp_enabled : true,
port: defaultcfg.udp_port || 2333,
running: udpServer !== null
};
});

// Dynamic Profile System IPC Handlers

ipcMain.on("create_profile", async (event, name) => {
Expand Down Expand Up @@ -446,14 +478,14 @@ function shutdownApplication() {
cleanupConnections();

// Close all servers
if (WServer) {
if (udpServer) {
console.log('Closing UDP server...');
try {
WServer.close();
udpServer.close();
} catch (e) {
console.error('Error closing UDP server:', e);
}
WServer = null;
udpServer = null;
}
if (qsyServer) {
console.log('Closing QSY server...');
Expand Down Expand Up @@ -601,6 +633,31 @@ if (!gotTheLock) {
app.quit();
});

// Load config from storage before starting servers
let storedcfg = storage.getSync('basic');
if (!(storedcfg.wavelog_url) && !(storedcfg.profiles)) {
// No saved config, use defaults
defaultcfg.profiles = [defaultcfg];
defaultcfg.profile = 0;
} else if (!(storedcfg.profiles)) {
// Old config without array, convert it
defaultcfg.profiles = [storedcfg, defaultcfg];
defaultcfg.profile = 0;
} else {
// Use saved config
defaultcfg = storedcfg;
}

// Ensure global UDP settings exist (migration for older configs)
if (defaultcfg.udp_enabled === undefined) {
defaultcfg.udp_enabled = true;
}
if (defaultcfg.udp_port === undefined) {
defaultcfg.udp_port = 2333;
}

console.log('Loaded config, UDP enabled:', defaultcfg.udp_enabled, 'port:', defaultcfg.udp_port);

startserver();
app.whenReady().then(() => {
if (!sleepable) {
Expand Down Expand Up @@ -794,15 +851,45 @@ function send2wavelog(o_cfg,adif, dryrun = false) {

}

const ports = [2333]; // Liste der Ports, an die Sie binden möchten
// Function to start UDP server with configured settings
function startUdpServer() {
// Close existing server if running
if (udpServer) {
try {
udpServer.close();
} catch (e) {
console.log('Error closing existing UDP server:', e);
}
udpServer = null;
}

const udpEnabled = defaultcfg.udp_enabled !== undefined ? defaultcfg.udp_enabled : true;
const udpPort = defaultcfg.udp_port || 2333;

if (!udpEnabled) {
console.log('UDP listener disabled');
tomsg('UDP Listener disabled');
return;
}

console.log('Starting UDP server on port ' + udpPort);

udpServer = udp.createSocket('udp4');

ports.forEach(port => {
WServer = udp.createSocket('udp4');
WServer.on('error', function(err) {
tomsg('Some other Tool blocks Port '+port+'. Stop it, and restart this');
udpServer.on('error', function(err) {
console.error('UDP server error:', err);
if (err.code === 'EADDRINUSE') {
tomsg('Port ' + udpPort + ' already in use. Stop the other application and restart.');
} else {
tomsg('UDP server error: ' + err.message);
}
});

WServer.on('message',async function(msg,info){
udpServer.on('listening', function() {
console.log('UDP server is listening on port ' + udpPort);
});

udpServer.on('message',async function(msg,info){
let parsedXML={};
let adobject={};
if (msg.toString().includes("xml")) { // detect if incoming String is XML
Expand All @@ -816,7 +903,7 @@ ports.forEach(port => {
parsedXML.contactinfo.mode[0]='SSB';
}
adobject = { qsos: [
{
{
CALL: parsedXML.contactinfo.call[0],
MODE: parsedXML.contactinfo.mode[0],
QSO_DATE_OFF: qsodat.d,
Expand Down Expand Up @@ -854,7 +941,7 @@ ports.forEach(port => {
const outadif=writeADIF(adobject);
plainret=await send2wavelog(defaultcfg.profiles[defaultcfg.profile ?? 0],outadif.stringify());
x.state=plainret.statusCode;
x.payload = JSON.parse(plainret.resString);
x.payload = JSON.parse(plainret.resString);
} catch(e) {
try {
x.payload=JSON.parse(e.resString);
Expand Down Expand Up @@ -885,8 +972,11 @@ ports.forEach(port => {
tomsg('<div class="alert alert-danger" role="alert">No ADIF detected. WSJT-X: Use ONLY Secondary UDP-Server</div>');
}
});
WServer.bind(port);
});

udpServer.bind(udpPort);
console.log('UDP server started on port '+udpPort);
tomsg('Waiting for QSO / Listening on UDP '+udpPort);
}

function tomsg(msg) {
try {
Expand Down Expand Up @@ -1321,7 +1411,8 @@ function startserver() {
// Setup SSL certificates
const certResult = setupCertificates();

tomsg('Waiting for QSO / Listening on UDP 2333');
// Start UDP server (will check config)
startUdpServer();

// Prompt for certificate installation if:
// 1. Cert was just generated, OR
Expand Down Expand Up @@ -1381,7 +1472,8 @@ function startserver() {
// Start Secure WebSocket server
startSecureWebSocketServer();
} catch(e) {
tomsg('Some other Tool blocks Port 2333 or 54321. Stop it, and restart this');
console.error('Error in startserver:', e);
tomsg('Some other Tool blocks Port 2333/54321/54322. Stop it, and restart this');
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Gateway for connecting WSJT-* and FLRig to Wavelog",
"keywords": [],
"main": "./main.js",
"version": "1.2.0",
"version": "1.2.1",
"author": "DJ7NT",
"scripts": {
"start": "electron-forge start",
Expand Down
54 changes: 54 additions & 0 deletions renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ $(document).ready(function() {
const index = parseInt($(this).closest('.list-group-item').data('index'));
deleteProfile(index);
});

// Advanced settings modal event listeners
$('#advanced').click(openAdvancedModal);
$('#advancedSave').click(saveAdvancedSettings);
$('#advancedCancel').click(() => $('#advancedModal').modal('hide'));
});

async function load_config() {
Expand Down Expand Up @@ -720,3 +725,52 @@ async function switchToSelectedProfile() {
$("#test").addClass('btn-primary');
$("#msg2").hide();
}

// Advanced Settings Modal Functions

function openAdvancedModal() {
$("#udp_enabled").prop('checked', cfg.udp_enabled !== undefined ? cfg.udp_enabled : true);
// Set port value (default to 2333 if undefined)
$("#udp_port").val(cfg.udp_port || 2333);
// Show current UDP status
updateUdpStatus();

$('#advancedModal').modal('show');
}

async function saveAdvancedSettings() {
cfg.udp_enabled = $("#udp_enabled").is(':checked');
cfg.udp_port = parseInt($("#udp_port").val()) || 2333;

if (cfg.profiles[active_cfg].udp_port < 1024 || cfg.profiles[active_cfg].udp_port > 65535) {
alert('Port must be between 1024 and 65535');
return;
}

cfg = await ipcRenderer.sendSync("set_config", cfg);
ipcRenderer.sendSync("restart_udp");

updateUdpStatus();

$('#advancedModal').modal('hide');
}

function updateUdpStatus() {
const status = ipcRenderer.sendSync("get_udp_status");
const statusDiv = $('#udp_status');
const statusText = $('#udp_status_text');

if (status.enabled) {
if (status.running) {
statusDiv.removeClass('alert-warning alert-danger').addClass('alert-info');
statusText.text('UDP Listener is running on port ' + status.port);
} else {
statusDiv.removeClass('alert-info alert-danger').addClass('alert-warning');
statusText.text('UDP Listener is enabled but not running (port: ' + status.port + ')');
}
} else {
statusDiv.removeClass('alert-info alert-warning').addClass('alert-secondary');
statusText.text('UDP Listener is disabled');
}
statusDiv.show();
}