You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-26 14:11:59 +01:00
bugfix pack, server logs
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
node_modules/
|
||||
/*.json
|
||||
/ffmpeg.exe
|
||||
/ffmpeg.exe
|
||||
/serverlog.txt
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fm-dx-webserver",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.9",
|
||||
"description": "FM DX Webserver",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const verboseMode = process.argv.includes('--debug');
|
||||
const verboseModeFfmpeg = process.argv.includes('--ffmpegdebug');
|
||||
|
||||
const ANSI_ESCAPE_CODE_PATTERN = /\x1b\[[0-9;]*m/g;
|
||||
const MAX_LOG_LINES = 100000;
|
||||
|
||||
const getCurrentTime = () => {
|
||||
const currentTime = new Date();
|
||||
const hours = currentTime.getHours().toString().padStart(2, '0');
|
||||
@@ -8,7 +13,12 @@ const getCurrentTime = () => {
|
||||
return `\x1b[90m[${hours}:${minutes}]\x1b[0m`;
|
||||
};
|
||||
|
||||
const removeANSIEscapeCodes = (str) => {
|
||||
return str.replace(ANSI_ESCAPE_CODE_PATTERN, '');
|
||||
};
|
||||
|
||||
const MESSAGE_PREFIX = {
|
||||
CHAT: "\x1b[36m[CHAT]\x1b[0m",
|
||||
DEBUG: "\x1b[36m[DEBUG]\x1b[0m",
|
||||
ERROR: "\x1b[31m[ERROR]\x1b[0m",
|
||||
FFMPEG: "\x1b[36m[FFMPEG]\x1b[0m",
|
||||
@@ -21,14 +31,20 @@ const logs = [];
|
||||
const maxLogLines = 250;
|
||||
|
||||
const logDebug = (...messages) => {
|
||||
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.DEBUG} ${messages.join(' ')}`;
|
||||
if (verboseMode) {
|
||||
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.DEBUG} ${messages.join(' ')}`;
|
||||
logs.push(logMessage);
|
||||
if (logs.length > maxLogLines) {
|
||||
logs.shift();
|
||||
}
|
||||
console.log(logMessage);
|
||||
}
|
||||
appendLogToFile(logMessage);
|
||||
};
|
||||
|
||||
const logChat = (...messages) => {
|
||||
const logMessage = `${getCurrentTime()} ${MESSAGE_PREFIX.CHAT} ${messages[0].nickname} (${messages[0].ip}) sent a chat message: ${messages[0].message}`;
|
||||
appendLogToFile(logMessage);
|
||||
};
|
||||
|
||||
const logError = (...messages) => {
|
||||
@@ -38,6 +54,7 @@ const logError = (...messages) => {
|
||||
logs.shift();
|
||||
}
|
||||
console.log(logMessage);
|
||||
appendLogToFile(logMessage);
|
||||
};
|
||||
|
||||
const logFfmpeg = (...messages) => {
|
||||
@@ -48,6 +65,7 @@ const logFfmpeg = (...messages) => {
|
||||
logs.shift();
|
||||
}
|
||||
console.log(logMessage);
|
||||
appendLogToFile(logMessage);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,6 +76,7 @@ const logInfo = (...messages) => {
|
||||
logs.shift();
|
||||
}
|
||||
console.log(logMessage);
|
||||
appendLogToFile(logMessage);
|
||||
};
|
||||
|
||||
const logWarn = (...messages) => {
|
||||
@@ -67,8 +86,36 @@ const logWarn = (...messages) => {
|
||||
logs.shift();
|
||||
}
|
||||
console.log(logMessage);
|
||||
appendLogToFile(logMessage);
|
||||
};
|
||||
|
||||
function appendLogToFile(logMessage) {
|
||||
const cleanLogMessage = removeANSIEscapeCodes(logMessage);
|
||||
|
||||
fs.appendFile('serverlog.txt', cleanLogMessage + '\n', (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing to server log:', err);
|
||||
} else {
|
||||
fs.readFile('serverlog.txt', 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading server log:', err);
|
||||
} else {
|
||||
const lineCount = data.split('\n').length;
|
||||
if (lineCount > MAX_LOG_LINES) {
|
||||
const excessLines = lineCount - MAX_LOG_LINES;
|
||||
const truncatedContent = data.split('\n').slice(excessLines).join('\n');
|
||||
fs.writeFile('serverlog.txt', truncatedContent, (err) => {
|
||||
if (err) {
|
||||
console.error('Error truncating server log:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
logError, logDebug, logFfmpeg, logInfo, logWarn, logs
|
||||
logError, logDebug, logFfmpeg, logInfo, logWarn, logs, logChat
|
||||
};
|
||||
|
||||
@@ -272,6 +272,8 @@ function handleData(ws, receivedData) {
|
||||
modifiedData = receivedLine.substring(1).split(",")[0];
|
||||
|
||||
if((modifiedData / 1000).toFixed(3) == dataToSend.freq) {
|
||||
resetToDefault(dataToSend);
|
||||
rdsparser.clear(rds);
|
||||
return; // Prevent tune spamming using scrollwheel
|
||||
}
|
||||
|
||||
@@ -386,13 +388,18 @@ function processSignal(receivedData, st, stForced) {
|
||||
initialData.st_forced = stForced;
|
||||
|
||||
if (!isNaN(parsedValue)) {
|
||||
dataToSend.signal = parsedValue.toFixed(2);
|
||||
initialData.signal = parsedValue.toFixed(2);
|
||||
// Convert parsedValue to a number
|
||||
var signal = parseFloat(parsedValue.toFixed(2));
|
||||
dataToSend.signal = signal;
|
||||
initialData.signal = signal;
|
||||
|
||||
if(dataToSend.signal > dataToSend.highestSignal) {
|
||||
dataToSend.highestSignal = dataToSend.signal;
|
||||
// Convert highestSignal to a number for comparison
|
||||
var highestSignal = parseFloat(dataToSend.highestSignal);
|
||||
if (signal > highestSignal) {
|
||||
dataToSend.highestSignal = signal.toString(); // Convert back to string for consistency
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -61,6 +61,10 @@ router.get('/', (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/403', (req, res) => {
|
||||
res.render('403');
|
||||
})
|
||||
|
||||
router.get('/wizard', (req, res) => {
|
||||
let serialPorts;
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ const { SerialPort } = require('serialport')
|
||||
const helpers = require('./helpers');
|
||||
const dataHandler = require('./datahandler');
|
||||
const fmdxList = require('./fmdx_list');
|
||||
const { logDebug, logError, logInfo, logWarn } = require('./console');
|
||||
const { logDebug, logError, logInfo, logWarn, logChat } = require('./console');
|
||||
const storage = require('./storage');
|
||||
const { configName, serverConfig, configUpdate, configSave } = require('./server_config');
|
||||
const { serverConfig } = require('./server_config');
|
||||
const pjson = require('../package.json');
|
||||
|
||||
console.log(`\x1b[32m
|
||||
@@ -70,19 +70,10 @@ function connectToSerial() {
|
||||
serialport.on('open', () => {
|
||||
logInfo('Using COM device: ' + serverConfig.xdrd.comPort);
|
||||
serialport.write('x\n');
|
||||
serialport.write('W0\n');
|
||||
serialport.write('M0\n');
|
||||
serverConfig.audio.startupVolume ? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n') : serialport.write('Y100\n');
|
||||
serialport.write('D0\n');
|
||||
serialport.write('A0\n');
|
||||
serialport.write('F-1\n');
|
||||
serialport.write('Z0\n');
|
||||
serialport.write('G11\n');
|
||||
serialport.write('V0\n');
|
||||
serialport.write('Q0\n');
|
||||
serialport.write('C0\n');
|
||||
serialport.write('I0,0\n');
|
||||
|
||||
serialport.write('M0\n');
|
||||
serialport.write('Z0\n');
|
||||
|
||||
if(serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true) {
|
||||
serialport.write('T' + Math.round(serverConfig.defaultFreq * 1000) +'\n');
|
||||
dataHandler.initialData.freq = Number(serverConfig.defaultFreq).toFixed(3);
|
||||
@@ -90,6 +81,13 @@ function connectToSerial() {
|
||||
} else {
|
||||
serialport.write('T87500\n');
|
||||
}
|
||||
|
||||
serialport.write('A0\n');
|
||||
serialport.write('F-1\n');
|
||||
serialport.write('W0\n');
|
||||
serialport.write('D0\n');
|
||||
serialport.write('G11\n');
|
||||
serverConfig.audio.startupVolume ? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n') : serialport.write('Y100\n');
|
||||
|
||||
serialport.on('data', (data) => {
|
||||
helpers.resolveDataBuffer(data, wss);
|
||||
@@ -158,11 +156,11 @@ function connectToXdrd() {
|
||||
dataHandler.dataToSend.ant = modifiedLine;
|
||||
}
|
||||
|
||||
if (authFlags.authMsg && authFlags.firstClient) {
|
||||
if (authFlags.authMsg === true && authFlags.firstClient === true) {
|
||||
client.write('x\n');
|
||||
client.write(serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? 'T' + Math.round(serverConfig.defaultFreq * 1000) + '\n' : 'T87500\n');
|
||||
dataHandler.initialData.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? (serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3);
|
||||
dataHandler.dataToSend.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? (serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3);
|
||||
dataHandler.initialData.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3);
|
||||
dataHandler.dataToSend.freq = serverConfig.defaultFreq && serverConfig.enableDefaultFreq === true ? Number(serverConfig.defaultFreq).toFixed(3) : (87.5).toFixed(3);
|
||||
client.write('A0\n');
|
||||
client.write(serverConfig.audio.startupVolume ? 'Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n' : 'Y100\n');
|
||||
client.off('data', authDataHandler);
|
||||
@@ -406,6 +404,7 @@ chatWss.on('connection', (ws, request) => {
|
||||
if (storage.chatHistory.length > 50) {
|
||||
storage.chatHistory.shift();
|
||||
}
|
||||
logChat(messageData);
|
||||
|
||||
const modifiedMessage = JSON.stringify(messageData);
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
<div class="panel-100 p-10">
|
||||
<br>
|
||||
<i class="text-big fa-solid fa-exclamation-triangle color-4"></i>
|
||||
<p>You are not authorized to use this tuner. Please try again later or contact the owner.</p>
|
||||
<p>You are not authorized to use this tuner. <br>
|
||||
There's a possibility you were kicked or banned by the administrator.<br>
|
||||
Please try again later or contact the owner.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -92,6 +92,11 @@ label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#data-station-container h2 {
|
||||
display: block !important;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#data-station-name {
|
||||
font-size: 20px;
|
||||
}
|
||||
@@ -309,11 +314,14 @@ pre {
|
||||
}
|
||||
.highest-signal-container {
|
||||
margin-top: -20px !important;
|
||||
margin-bottom: 15px !important;
|
||||
margin-bottom: -15px !important;
|
||||
}
|
||||
#pi-code-container {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
#data-pi {
|
||||
font-size: 24px;
|
||||
margin-top: 20px;
|
||||
margin-top: 5px;
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
h2.show-phone {
|
||||
@@ -324,16 +332,18 @@ pre {
|
||||
font-size: 42px;
|
||||
}
|
||||
#data-frequency {
|
||||
font-size: 72px;
|
||||
font-size: 64px;
|
||||
}
|
||||
#data-rt0, #data-rt1 {
|
||||
font-size: 10px;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
overflow-x:auto;
|
||||
padding: 5px 0;
|
||||
}
|
||||
#rt-container {
|
||||
height: 32px !important;
|
||||
height: max-content !important;
|
||||
}
|
||||
ul {
|
||||
font-size: 16px;
|
||||
@@ -376,10 +386,12 @@ pre {
|
||||
#af-list ul {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
#rt-container {
|
||||
order: 2;
|
||||
}
|
||||
.modal-panel-footer {
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 769px) and (max-height: 860px) {
|
||||
@@ -412,6 +424,14 @@ pre {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h2.signal-heading {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.highest-signal-container {
|
||||
margin-bottom: -10px !important;
|
||||
}
|
||||
|
||||
h2.mb-0 {
|
||||
margin-bottom: 0;
|
||||
margin-top: 2px !important;
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<div style="display:inline-block">
|
||||
<span style="margin-left: 20px;display: block;margin-top: 2px;" class="data-flag"></span>
|
||||
</div>
|
||||
<span id="stereo-container" class="pointer" style="position: relative;">
|
||||
<span class="pointer stereo-container" style="position: relative;">
|
||||
<span style="margin-left: 20px;" class="data-st">ST</span>
|
||||
<span class="overlay tooltip" data-tooltip="Stereo / Mono toggle. <br><strong>Click to toggle."></span>
|
||||
</span>
|
||||
@@ -98,7 +98,7 @@
|
||||
</div>
|
||||
|
||||
<div class="panel-33">
|
||||
<h2>SIGNAL</h2>
|
||||
<h2 class="signal-heading">SIGNAL</h2>
|
||||
<div class="text-small text-gray highest-signal-container">
|
||||
<i class="fa-solid fa-arrow-up"></i>
|
||||
<span id="data-signal-highest"></span>
|
||||
@@ -120,7 +120,7 @@
|
||||
</div>
|
||||
|
||||
<% if (antennas.enabled == true) { %>
|
||||
<div class="panel-50 no-bg h-100 m-0 dropdown" id="data-ant" style="margin-right: 25px;width:125px;">
|
||||
<div class="panel-50 no-bg h-100 m-0 dropdown" id="data-ant" style="margin-right: 25px;">
|
||||
<input type="text" placeholder="Ant A" readonly>
|
||||
<ul class="options">
|
||||
<% if(antennas.ant1.enabled == true) { %><li data-value="0" class="option"><%= antennas.ant1.name %></li><% } %>
|
||||
@@ -249,8 +249,12 @@
|
||||
<div class="flex-container flex-phone flex-phone-column">
|
||||
<div class="panel-75 hover-brighten" id="rt-container" style="height: 100px;">
|
||||
<h2 style="margin-top: 4px;">RADIOTEXT</h2>
|
||||
<div id="data-rt0"></div>
|
||||
<div id="data-rt1"></div>
|
||||
<div id="data-rt0">
|
||||
<span></span>
|
||||
</div>
|
||||
<div id="data-rt1">
|
||||
<span></span>
|
||||
</div>
|
||||
<hr class="hide-desktop">
|
||||
</div>
|
||||
|
||||
@@ -297,7 +301,10 @@
|
||||
<div style="display:inline-block">
|
||||
<span style="margin-left: 20px;display: block;margin-top: 2px;" class="data-flag"></span>
|
||||
</div>
|
||||
<span style="margin-left: 20px;" class="data-st"></span>
|
||||
<span class="pointer stereo-container" style="position: relative;">
|
||||
<span style="margin-left: 20px;" class="data-st">ST</span>
|
||||
<span class="overlay tooltip" data-tooltip="Stereo / Mono toggle. <br><strong>Click to toggle."></span>
|
||||
</span>
|
||||
<span style="margin-left: 15px;" class="data-ms">MS</span>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -74,15 +74,15 @@ $(document).ready(function() {
|
||||
if (savedNickname) {
|
||||
chatNicknameInput.val(savedNickname);
|
||||
}
|
||||
});
|
||||
|
||||
function sendMessage() {
|
||||
const nickname = chatNicknameInput.val().trim() || 'Anonymous user';
|
||||
const message = chatSendInput.val().trim();
|
||||
|
||||
if (message) {
|
||||
const messageData = { nickname, message };
|
||||
chatSocket.send(JSON.stringify(messageData));
|
||||
chatSendInput.val('');
|
||||
function sendMessage() {
|
||||
const nickname = savedNickname || 'Anonymous user';
|
||||
const message = chatSendInput.val().trim();
|
||||
|
||||
if (message) {
|
||||
const messageData = { nickname, message };
|
||||
chatSocket.send(JSON.stringify(messageData));
|
||||
chatSendInput.val('');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,9 +1,9 @@
|
||||
var currentDate = new Date('March 25, 2024 23:00:00');
|
||||
var currentDate = new Date('March 28, 2024 22:00:00');
|
||||
var day = currentDate.getDate();
|
||||
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
|
||||
var year = currentDate.getFullYear();
|
||||
var formattedDate = day + '/' + month + '/' + year;
|
||||
var currentVersion = 'v1.1.8 [' + formattedDate + ']';
|
||||
var currentVersion = 'v1.1.9 [' + formattedDate + ']';
|
||||
|
||||
getInitialSettings();
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ $(document).ready(function () {
|
||||
$(rtContainer).on("click", copyRt);
|
||||
$(txContainer).on("click", copyTx);
|
||||
$(piCodeContainer).on("click", findOnMaps);
|
||||
$(document).on("click", "#stereo-container", toggleForcedStereo);
|
||||
$(document).on("click", ".stereo-container", toggleForcedStereo);
|
||||
$(freqContainer).on("click", function () {
|
||||
textInput.focus();
|
||||
});
|
||||
@@ -476,9 +476,7 @@ function tuneDown() {
|
||||
}
|
||||
|
||||
function tuneTo(freq) {
|
||||
if (socket.readyState === WebSocket.OPEN) {
|
||||
socket.send("T" + ((freq).toFixed(1) * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
async function copyPs() {
|
||||
@@ -513,8 +511,8 @@ async function copyTx() {
|
||||
}
|
||||
|
||||
async function copyRt() {
|
||||
var rt0 = $('#data-rt0').text();
|
||||
var rt1 = $('#data-rt1').text();
|
||||
var rt0 = $('#data-rt0 span').text();
|
||||
var rt1 = $('#data-rt1 span').text();
|
||||
|
||||
try {
|
||||
await copyToClipboard("[0] RT: " + rt0 + "\n[1] RT: " + rt1);
|
||||
@@ -578,11 +576,13 @@ function updateSignalUnits(parsedData, averageSignal) {
|
||||
switch (signalUnit) {
|
||||
case 'dbuv':
|
||||
signalValue = currentSignal - 11.25;
|
||||
highestSignal = highestSignal - 11.25;
|
||||
signalText.text('dBµV');
|
||||
break;
|
||||
|
||||
case 'dbm':
|
||||
signalValue = currentSignal - 120;
|
||||
highestSignal = highestSignal - 120;
|
||||
signalText.text('dBm');
|
||||
break;
|
||||
|
||||
@@ -606,8 +606,8 @@ function updateDataElements(parsedData) {
|
||||
const $dataPi = $('#data-pi');
|
||||
const $dataPs = $('#data-ps');
|
||||
const $dataSt = $('.data-st');
|
||||
const $dataRt0 = $('#data-rt0');
|
||||
const $dataRt1 = $('#data-rt1');
|
||||
const $dataRt0 = $('#data-rt0 span');
|
||||
const $dataRt1 = $('#data-rt1 span');
|
||||
const $dataAntInput = $('#data-ant input');
|
||||
const $dataBwInput = $('#data-bw input');
|
||||
const $dataStationContainer = $('#data-station-container');
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
<div class="panel-100 no-bg">
|
||||
<h3>Themes</h3>
|
||||
<div class="form-group">
|
||||
<label for="themes"><i class="fa-solid fa-palette"></i>Default server theme:</label>
|
||||
<label for="themes"><i class="fa-solid fa-palette"></i> Default server theme:</label>
|
||||
<div class="dropdown" id="server-theme-selector" style="margin-right: 0;">
|
||||
<input type="text" placeholder="Default" id="selected-theme" readonly>
|
||||
<ul class="options">
|
||||
@@ -509,6 +509,7 @@
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<script src="js/init.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<script src="js/dropdown.js"></script>
|
||||
<script src="js/setup.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user