mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-31 09:19:16 +02:00
logging improvements, connection changes, ui changes
This commit is contained in:
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
const verboseMode = process.argv.includes('--debug');
|
const verboseMode = process.argv.includes('--debug');
|
||||||
|
const verboseModeFfmpeg = process.argv.includes('--ffmpegdebug');
|
||||||
|
|
||||||
const getCurrentTime = () => {
|
const getCurrentTime = () => {
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
@@ -10,6 +11,7 @@ const getCurrentTime = () => {
|
|||||||
const MESSAGE_PREFIX = {
|
const MESSAGE_PREFIX = {
|
||||||
DEBUG: "\x1b[36m[DEBUG]\x1b[0m",
|
DEBUG: "\x1b[36m[DEBUG]\x1b[0m",
|
||||||
ERROR: "\x1b[31m[ERROR]\x1b[0m",
|
ERROR: "\x1b[31m[ERROR]\x1b[0m",
|
||||||
|
FFMPEG: "\x1b[36m[FFMPEG]\x1b[0m",
|
||||||
INFO: "\x1b[32m[INFO]\x1b[0m",
|
INFO: "\x1b[32m[INFO]\x1b[0m",
|
||||||
WARN: "\x1b[33m[WARN]\x1b[0m",
|
WARN: "\x1b[33m[WARN]\x1b[0m",
|
||||||
};
|
};
|
||||||
@@ -38,6 +40,17 @@ const logError = (...messages) => {
|
|||||||
console.log(logMessage);
|
console.log(logMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const logFfmpeg = (...messages) => {
|
||||||
|
if (verboseModeFfmpeg) {
|
||||||
|
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.FFMPEG} ${messages.join(' ')}`;
|
||||||
|
logs.push(logMessage);
|
||||||
|
if (logs.length > maxLogLines) {
|
||||||
|
logs.shift(); // Remove the oldest log if the array exceeds the maximum number of lines
|
||||||
|
}
|
||||||
|
console.log(logMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const logInfo = (...messages) => {
|
const logInfo = (...messages) => {
|
||||||
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.INFO} ${messages.join(' ')}`;
|
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.INFO} ${messages.join(' ')}`;
|
||||||
logs.push(logMessage);
|
logs.push(logMessage);
|
||||||
@@ -57,5 +70,5 @@ const logWarn = (...messages) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
logError, logDebug, logInfo, logWarn, logs
|
logError, logDebug, logFfmpeg, logInfo, logWarn, logs
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -341,7 +341,7 @@ function handleData(ws, receivedData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the received TX info
|
// Get the received TX info
|
||||||
const currentTx = fetchTx(dataToSend.freq, dataToSend.pi, dataToSend.ps);
|
const currentTx = fetchTx(parseFloat(dataToSend.freq).toFixed(1), dataToSend.pi, dataToSend.ps);
|
||||||
if(currentTx && currentTx.station !== undefined) {
|
if(currentTx && currentTx.station !== undefined) {
|
||||||
dataToSend.txInfo = {
|
dataToSend.txInfo = {
|
||||||
station: currentTx.station,
|
station: currentTx.station,
|
||||||
|
|||||||
@@ -100,106 +100,117 @@ function authenticateWithXdrd(client, salt, password) {
|
|||||||
client.write('x\n');
|
client.write('x\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serverConfig.identification.tunerName.includes('zvartoshu')) {
|
connectToXdrd();
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// xdrd connection
|
// xdrd connection
|
||||||
if (serverConfig.xdrd.xdrdPassword.length > 1) {
|
function connectToXdrd() {
|
||||||
client.connect(serverConfig.xdrd.xdrdPort, serverConfig.xdrd.xdrdIp, () => {
|
if (serverConfig.xdrd.xdrdPassword.length > 1) {
|
||||||
logInfo('Connection to xdrd established successfully.');
|
client.connect(serverConfig.xdrd.xdrdPort, serverConfig.xdrd.xdrdIp, () => {
|
||||||
|
logInfo('Connection to xdrd established successfully.');
|
||||||
const authFlags = {
|
|
||||||
authMsg: false,
|
|
||||||
firstClient: false,
|
|
||||||
receivedPassword: false
|
|
||||||
};
|
|
||||||
|
|
||||||
const authDataHandler = (data) => {
|
|
||||||
const receivedData = data.toString();
|
|
||||||
const lines = receivedData.split('\n');
|
|
||||||
|
|
||||||
for (const line of lines) {
|
const authFlags = {
|
||||||
|
authMsg: false,
|
||||||
|
firstClient: false,
|
||||||
|
receivedPassword: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const authDataHandler = (data) => {
|
||||||
|
const receivedData = data.toString();
|
||||||
|
const lines = receivedData.split('\n');
|
||||||
|
|
||||||
if (!authFlags.receivedPassword) {
|
for (const line of lines) {
|
||||||
authFlags.receivedSalt = line.trim();
|
|
||||||
authenticateWithXdrd(client, authFlags.receivedSalt, serverConfig.xdrd.xdrdPassword);
|
|
||||||
authFlags.receivedPassword = true;
|
|
||||||
} else {
|
|
||||||
if (line.startsWith('a')) {
|
|
||||||
authFlags.authMsg = true;
|
|
||||||
logWarn('Authentication with xdrd failed. Is your password set correctly?');
|
|
||||||
} else if (line.startsWith('o1,')) {
|
|
||||||
authFlags.firstClient = true;
|
|
||||||
} else if (line.startsWith('T') && line.length <= 7) {
|
|
||||||
const freq = line.slice(1) / 1000;
|
|
||||||
dataHandler.dataToSend.freq = freq.toFixed(3);
|
|
||||||
} else if (line.startsWith('OK')) {
|
|
||||||
authFlags.authMsg = true;
|
|
||||||
logInfo('Authentication with xdrd successful.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authFlags.authMsg && authFlags.firstClient) {
|
if (!authFlags.receivedPassword) {
|
||||||
client.write('T87500\n');
|
authFlags.receivedSalt = line.trim();
|
||||||
client.write('A0\n');
|
authenticateWithXdrd(client, authFlags.receivedSalt, serverConfig.xdrd.xdrdPassword);
|
||||||
client.write('G11\n');
|
authFlags.receivedPassword = true;
|
||||||
client.off('data', authDataHandler);
|
} else {
|
||||||
return;
|
if (line.startsWith('a')) {
|
||||||
|
authFlags.authMsg = true;
|
||||||
|
logWarn('Authentication with xdrd failed. Is your password set correctly?');
|
||||||
|
} else if (line.startsWith('o1,')) {
|
||||||
|
authFlags.firstClient = true;
|
||||||
|
} else if (line.startsWith('T') && line.length <= 7) {
|
||||||
|
const freq = line.slice(1) / 1000;
|
||||||
|
dataHandler.dataToSend.freq = freq.toFixed(3);
|
||||||
|
} else if (line.startsWith('OK')) {
|
||||||
|
authFlags.authMsg = true;
|
||||||
|
logInfo('Authentication with xdrd successful.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authFlags.authMsg && authFlags.firstClient) {
|
||||||
|
client.write('T87500\n');
|
||||||
|
client.write('A0\n');
|
||||||
|
client.write('G11\n');
|
||||||
|
client.off('data', authDataHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
client.on('data', (data) => {
|
|
||||||
var receivedData = incompleteDataBuffer + data.toString();
|
|
||||||
const isIncomplete = (receivedData.slice(-1) != '\n');
|
|
||||||
|
|
||||||
if (isIncomplete) {
|
client.on('data', (data) => {
|
||||||
const position = receivedData.lastIndexOf('\n');
|
var receivedData = incompleteDataBuffer + data.toString();
|
||||||
if (position < 0) {
|
const isIncomplete = (receivedData.slice(-1) != '\n');
|
||||||
incompleteDataBuffer = receivedData;
|
|
||||||
receivedData = '';
|
if (isIncomplete) {
|
||||||
|
const position = receivedData.lastIndexOf('\n');
|
||||||
|
if (position < 0) {
|
||||||
|
incompleteDataBuffer = receivedData;
|
||||||
|
receivedData = '';
|
||||||
|
} else {
|
||||||
|
incompleteDataBuffer = receivedData.slice(position + 1);
|
||||||
|
receivedData = receivedData.slice(0, position + 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
incompleteDataBuffer = receivedData.slice(position + 1);
|
incompleteDataBuffer = '';
|
||||||
receivedData = receivedData.slice(0, position + 1);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
incompleteDataBuffer = '';
|
if (receivedData.length) {
|
||||||
}
|
wss.clients.forEach((client) => {
|
||||||
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
|
dataHandler.handleData(client, receivedData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (receivedData.length) {
|
client.on('data', authDataHandler);
|
||||||
wss.clients.forEach((client) => {
|
|
||||||
if (client.readyState === WebSocket.OPEN) {
|
|
||||||
dataHandler.handleData(client, receivedData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
client.on('data', authDataHandler);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on('close', () => {
|
client.on('close', () => {
|
||||||
logWarn('Disconnected from xdrd.');
|
logWarn('Disconnected from xdrd. Attempting to reconnect.');
|
||||||
|
setTimeout(function () {
|
||||||
|
connectToXdrd();
|
||||||
|
}, 2000)
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('error', (err) => {
|
client.on('error', (err) => {
|
||||||
|
setTimeout(function () {
|
||||||
|
connectToXdrd();
|
||||||
|
}, 2000)
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case err.message.includes("ECONNRESET"):
|
case err.message.includes("ECONNRESET"):
|
||||||
logError("Connection to xdrd lost. Exiting...");
|
logError("Connection to xdrd lost. Reconnecting...");
|
||||||
process.exit(1);
|
break;
|
||||||
|
|
||||||
case err.message.includes("ETIMEDOUT"):
|
case err.message.includes("ETIMEDOUT"):
|
||||||
logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xrd.xdrdPort + " timed out.");
|
logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " timed out.");
|
||||||
process.exit(1);
|
break;
|
||||||
|
|
||||||
case err.message.includes("ECONNREFUSED"):
|
case err.message.includes("ECONNREFUSED"):
|
||||||
logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " failed. Is xdrd running?");
|
logError("Connection to xdrd @ " + serverConfig.xdrd.xdrdIp + ":" + serverConfig.xdrd.xdrdPort + " failed. Is xdrd running?");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case err.message.includes("EINVAL"):
|
||||||
|
logError("Attempts to reconnect are failing repeatedly. Consider checking your settings or restarting xdrd.");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logError("Unhandled error: ", err.message);
|
logError("Unhandled error: ", err.message);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -43,21 +43,21 @@ function enableAudioStream() {
|
|||||||
|
|
||||||
// Handle the output of the child process (optional)
|
// Handle the output of the child process (optional)
|
||||||
childProcess.stdout.on('data', (data) => {
|
childProcess.stdout.on('data', (data) => {
|
||||||
consoleCmd.logDebug(`stdout: ${data}`);
|
consoleCmd.logFfmpeg(`stdout: ${data}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
childProcess.stderr.on('data', (data) => {
|
childProcess.stderr.on('data', (data) => {
|
||||||
consoleCmd.logDebug(`stderr: ${data}`);
|
consoleCmd.logFfmpeg(`stderr: ${data}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle the child process exit event
|
// Handle the child process exit event
|
||||||
childProcess.on('close', (code) => {
|
childProcess.on('close', (code) => {
|
||||||
consoleCmd.logDebug(`Child process exited with code ${code}`);
|
consoleCmd.logFfmpeg(`Child process exited with code ${code}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// You can also listen for the 'error' event in case the process fails to start
|
// You can also listen for the 'error' event in case the process fails to start
|
||||||
childProcess.on('error', (err) => {
|
childProcess.on('error', (err) => {
|
||||||
consoleCmd.logError(`Error starting child process: ${err}`);
|
consoleCmd.logFfmpeg(`Error starting child process: ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ label {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 960px) and (max-height: 860px) {
|
@media only screen and (min-width: 769px) and (max-height: 860px) {
|
||||||
#rt-container {
|
#rt-container {
|
||||||
height: 90px !important;
|
height: 90px !important;
|
||||||
}
|
}
|
||||||
@@ -268,4 +268,8 @@ label {
|
|||||||
float: right;
|
float: right;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
h2 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -84,13 +84,6 @@ input[type="range"] {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="range"]::after {
|
|
||||||
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
background: blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Track: Mozilla Firefox */
|
/* Track: Mozilla Firefox */
|
||||||
input[type="range"]::-moz-range-track {
|
input[type="range"]::-moz-range-track {
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
|||||||
+2
-2
@@ -133,7 +133,7 @@
|
|||||||
|
|
||||||
<div class="panel-33 flex-container flex-phone" id="tune-buttons">
|
<div class="panel-33 flex-container flex-phone" id="tune-buttons">
|
||||||
<button id="freq-down" aria-label="Tune down by 100 KHz"><i class="fa-solid fa-chevron-left"></i></button>
|
<button id="freq-down" aria-label="Tune down by 100 KHz"><i class="fa-solid fa-chevron-left"></i></button>
|
||||||
<input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency">
|
<input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency" aria-label="Current frequency: ">
|
||||||
<button id="freq-up" aria-label="Tune up by 100 KHz"><i class="fa-solid fa-chevron-right"></i></button>
|
<button id="freq-up" aria-label="Tune up by 100 KHz"><i class="fa-solid fa-chevron-right"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@
|
|||||||
<div class="flex-container flex-left text-left bottom-20 hover-brighten p-10 br-5" onclick="window.open('https://buymeacoffee.com/noobish')">
|
<div class="flex-container flex-left text-left bottom-20 hover-brighten p-10 br-5" onclick="window.open('https://buymeacoffee.com/noobish')">
|
||||||
<i class="fa-solid fa-hand-holding-medical"></i> <span><strong>Support</strong> the developer!</span>
|
<i class="fa-solid fa-hand-holding-medical"></i> <span><strong>Support</strong> the developer!</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-small">FM-DX WebServer <span style="color: var(--color-3);">v1.0.2 [6/2/2024]</span> by <a href="https://noobish.eu" target="_blank">Noobish</a> & the OpenRadio community.</p>
|
<p class="text-small">FM-DX WebServer <span style="color: var(--color-3);">v1.0.3 [7/2/2024]</span> by <a href="https://noobish.eu" target="_blank">Noobish</a> & the OpenRadio community.</p>
|
||||||
<p class="text-small bottom-50">This app works thanks to these amazing projects: <br>
|
<p class="text-small bottom-50">This app works thanks to these amazing projects: <br>
|
||||||
<span class="text-smaller">- librdsparser & maps.fmdx.pl by <a href="https://fmdx.pl" target="_blank">Konrad Kosmatka</a></span><br>
|
<span class="text-smaller">- librdsparser & maps.fmdx.pl by <a href="https://fmdx.pl" target="_blank">Konrad Kosmatka</a></span><br>
|
||||||
<span class="text-smaller">- 3LAS by <a href="https://github.com/JoJoBond/3LAS" target="_blank">JoJoBond</a></span><br>
|
<span class="text-smaller">- 3LAS by <a href="https://github.com/JoJoBond/3LAS" target="_blank">JoJoBond</a></span><br>
|
||||||
|
|||||||
Reference in New Issue
Block a user