You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-26 22:13:53 +01:00
Merge branch 'main' of https://github.com/NoobishSVK/fm-dx-webserver
This commit is contained in:
@@ -80,11 +80,16 @@ if (serverConfig.xdrd.wirelessConnection === false) {
|
|||||||
serialport.open((err) => {
|
serialport.open((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logError('Error opening port: ' + err.message);
|
logError('Error opening port: ' + err.message);
|
||||||
|
setTimeout(() => {
|
||||||
|
connectToSerial();
|
||||||
|
}, 5000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo('Using COM device: ' + serverConfig.xdrd.comPort);
|
logInfo('Using COM device: ' + serverConfig.xdrd.comPort);
|
||||||
serialport.write('x\n');
|
setTimeout(() => {
|
||||||
|
serialport.write('x\n');
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
serialport.write('Q0\n');
|
serialport.write('Q0\n');
|
||||||
@@ -107,7 +112,7 @@ if (serverConfig.xdrd.wirelessConnection === false) {
|
|||||||
serverConfig.audio.startupVolume
|
serverConfig.audio.startupVolume
|
||||||
? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n')
|
? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n')
|
||||||
: serialport.write('Y100\n');
|
: serialport.write('Y100\n');
|
||||||
}, 3000);
|
}, 6000);
|
||||||
|
|
||||||
serialport.on('data', (data) => {
|
serialport.on('data', (data) => {
|
||||||
helpers.resolveDataBuffer(data, wss, rdsWss);
|
helpers.resolveDataBuffer(data, wss, rdsWss);
|
||||||
@@ -118,6 +123,13 @@ if (serverConfig.xdrd.wirelessConnection === false) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle port closure
|
||||||
|
serialport.on('close', () => {
|
||||||
|
logWarn('Disconnected from ' + serverConfig.xdrd.comPort + '. Attempting to reconnect.');
|
||||||
|
setTimeout(() => {
|
||||||
|
connectToSerial();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
return serialport;
|
return serialport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,14 +244,20 @@ label {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay {
|
#flags-container-phone,
|
||||||
|
#flags-container-desktop {
|
||||||
|
position: relative; /* Confine overlay within container which is necessary for iPhones */
|
||||||
|
}
|
||||||
|
|
||||||
|
#flags-container-phone .overlay,
|
||||||
|
#flags-container-desktop .overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
pointer-events: auto; /* Ensure that the overlay captures clicks */
|
bottom: 0;
|
||||||
opacity: 0; /* Make the overlay invisible */
|
pointer-events: auto;
|
||||||
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-quick-dashboard {
|
.admin-quick-dashboard {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
var elapsedTimeConnectionWatchdog;
|
||||||
var _3LAS_Settings = /** @class */ (function () {
|
var _3LAS_Settings = /** @class */ (function () {
|
||||||
function _3LAS_Settings() {
|
function _3LAS_Settings() {
|
||||||
this.SocketHost = document.location.hostname ? document.location.hostname : "127.0.0.1";
|
this.SocketHost = document.location.hostname ? document.location.hostname : "127.0.0.1";
|
||||||
@@ -47,6 +48,29 @@ var _3LAS = /** @class */ (function () {
|
|||||||
this.ConnectivityFlag = false;
|
this.ConnectivityFlag = false;
|
||||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
||||||
|
|
||||||
|
// Stream connection watchdog monitors mp3 frames
|
||||||
|
console.log("Stream connection watchdog active.");
|
||||||
|
let intervalReconnectWatchdog = setInterval(() => {
|
||||||
|
if (Stream) {
|
||||||
|
var endTimeConnectionWatchdog = performance.now();
|
||||||
|
elapsedTimeConnectionWatchdog = endTimeConnectionWatchdog - window.startTimeConnectionWatchdog;
|
||||||
|
//console.log(`Stream frame elapsed time: ${elapsedTimeConnectionWatchdog} ms`);
|
||||||
|
if (elapsedTimeConnectionWatchdog > 2000 && shouldReconnect) {
|
||||||
|
clearInterval(intervalReconnectWatchdog);
|
||||||
|
setTimeout(() => {
|
||||||
|
clearInterval(intervalReconnectWatchdog);
|
||||||
|
console.log("Unstable internet connection detected, reconnecting (" + elapsedTimeConnectionWatchdog + " ms)...");
|
||||||
|
this.Stop();
|
||||||
|
this.Start();
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearInterval(intervalReconnectWatchdog);
|
||||||
|
this.Stop();
|
||||||
|
console.log("Stream connection watchdog inactive.");
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
// This is stupid, but required for Android.... thanks Google :(
|
// This is stupid, but required for Android.... thanks Google :(
|
||||||
if (this.WakeLock)
|
if (this.WakeLock)
|
||||||
this.WakeLock.Begin();
|
this.WakeLock.Begin();
|
||||||
@@ -54,8 +78,8 @@ var _3LAS = /** @class */ (function () {
|
|||||||
if (window.location.protocol === 'https:') {
|
if (window.location.protocol === 'https:') {
|
||||||
this.WebSocket = new WebSocketClient(this.Logger, 'wss://' + this.Settings.SocketHost + ':' + location.port.toString() + window.location.pathname + 'audio' , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this));
|
this.WebSocket = new WebSocketClient(this.Logger, 'wss://' + this.Settings.SocketHost + ':' + location.port.toString() + window.location.pathname + 'audio' , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.WebSocket = new WebSocketClient(this.Logger, 'ws://' + this.Settings.SocketHost + ':' + location.port.toString() + window.location.pathname + 'audio' , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this));
|
this.WebSocket = new WebSocketClient(this.Logger, 'ws://' + this.Settings.SocketHost + ':' + location.port.toString() + window.location.pathname + 'audio' , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this));
|
||||||
}
|
}
|
||||||
this.Logger.Log("Init of WebSocketClient succeeded");
|
this.Logger.Log("Init of WebSocketClient succeeded");
|
||||||
this.Logger.Log("Trying to connect to server.");
|
this.Logger.Log("Trying to connect to server.");
|
||||||
@@ -130,45 +154,6 @@ var _3LAS = /** @class */ (function () {
|
|||||||
if (this.ConnectivityCallback)
|
if (this.ConnectivityCallback)
|
||||||
this.ConnectivityCallback(false);
|
this.ConnectivityCallback(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldReconnect) {
|
|
||||||
if (!this.ConnectivityFlag) {
|
|
||||||
console.log("Initial reconnect attempt...");
|
|
||||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
|
||||||
this.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delay launch of subsequent reconnect attempts by 3 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
|
|
||||||
let streamReconnecting = false;
|
|
||||||
|
|
||||||
let intervalReconnect = setInterval(() => {
|
|
||||||
if (this.ConnectivityFlag || typeof Stream === 'undefined' || Stream === null) {
|
|
||||||
console.log("Reconnect attempts aborted.");
|
|
||||||
clearInterval(intervalReconnect);
|
|
||||||
} else if (!streamReconnecting) {
|
|
||||||
streamReconnecting = true;
|
|
||||||
console.log("Attempting to restart stream...");
|
|
||||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
|
||||||
this.Start();
|
|
||||||
// Wait for reconnect attempt
|
|
||||||
setTimeout(() => {
|
|
||||||
streamReconnecting = false;
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
// Restore user set volume
|
|
||||||
if (Stream && typeof newVolumeGlobal !== 'undefined' && newVolumeGlobal !== null) {
|
|
||||||
Stream.Volume = newVolumeGlobal;
|
|
||||||
console.log(`User volume restored: ${Math.round(newVolumeGlobal * 100)}%`);
|
|
||||||
}
|
|
||||||
}, 3000);
|
|
||||||
|
|
||||||
}, 3000);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.Logger.Log("Reconnection is disabled.");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_3LAS.prototype.OnSocketDataReady = function (data) {
|
_3LAS.prototype.OnSocketDataReady = function (data) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
MPEG audio format reader is part of 3LAS (Low Latency Live Audio Streaming)
|
MPEG audio format reader is part of 3LAS (Low Latency Live Audio Streaming)
|
||||||
https://github.com/JoJoBond/3LAS
|
https://github.com/JoJoBond/3LAS
|
||||||
*/
|
*/
|
||||||
|
window.startTimeConnectionWatchdog = performance.now();
|
||||||
var __extends = (this && this.__extends) || (function () {
|
var __extends = (this && this.__extends) || (function () {
|
||||||
var extendStatics = function (d, b) {
|
var extendStatics = function (d, b) {
|
||||||
extendStatics = Object.setPrototypeOf ||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
@@ -194,6 +195,7 @@ var AudioFormatReader_MPEG = /** @class */ (function (_super) {
|
|||||||
};
|
};
|
||||||
// Is called if the decoding of the window succeeded
|
// Is called if the decoding of the window succeeded
|
||||||
AudioFormatReader_MPEG.prototype.OnDecodeSuccess = function (decodedData, id, expectedTotalPlayTime, firstGranulePlayTime, lastGranulePlayTime) {
|
AudioFormatReader_MPEG.prototype.OnDecodeSuccess = function (decodedData, id, expectedTotalPlayTime, firstGranulePlayTime, lastGranulePlayTime) {
|
||||||
|
window.startTimeConnectionWatchdog = performance.now();
|
||||||
var extractSampleCount;
|
var extractSampleCount;
|
||||||
var extractSampleOffset;
|
var extractSampleOffset;
|
||||||
var delta = 0.001;
|
var delta = 0.001;
|
||||||
|
|||||||
@@ -63,9 +63,24 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if device is an iPhone to prevent zoom on button press
|
||||||
|
if (/iPhone|iPod|iPad/.test(navigator.userAgent) && !window.MSStream) {
|
||||||
|
const buttons = document.querySelectorAll('button');
|
||||||
|
buttons.forEach(button => {
|
||||||
|
button.addEventListener('touchstart', function(e) {
|
||||||
|
// Prevent default zoom behavior
|
||||||
|
e.preventDefault();
|
||||||
|
// Allow default button action after short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
e.target.click();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const textInput = $('#commandinput');
|
const textInput = $('#commandinput');
|
||||||
|
|
||||||
textInput.on('change', function (event) {
|
textInput.on('change blur', function (event) {
|
||||||
const inputValue = Number(textInput.val());
|
const inputValue = Number(textInput.val());
|
||||||
// Check if the user agent contains 'iPhone'
|
// Check if the user agent contains 'iPhone'
|
||||||
if (/iPhone/i.test(navigator.userAgent)) {
|
if (/iPhone/i.test(navigator.userAgent)) {
|
||||||
@@ -219,8 +234,46 @@ function sendPingRequest() {
|
|||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error fetching ping:', error);
|
console.error('Error fetching ping:', error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Automatic reconnection on WebSocket close
|
||||||
|
if (socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING) {
|
||||||
|
socket = new WebSocket(socketAddress);
|
||||||
|
|
||||||
|
socket.onopen = () => {
|
||||||
|
console.log("Main/UI reconnected successfully.");
|
||||||
|
};
|
||||||
|
socket.onmessage = (event) => {
|
||||||
|
handleWebSocketMessage(event);
|
||||||
|
};
|
||||||
|
socket.onerror = (error) => {
|
||||||
|
console.error("Main/UI WebSocket error during reconnection:", error);
|
||||||
|
};
|
||||||
|
socket.onclose = () => {
|
||||||
|
console.warn("Main/UI WebSocket closed during reconnection. Will attempt to reconnect...");
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Automatic UI resume on WebSocket reconnect
|
||||||
|
function handleWebSocketMessage(event) {
|
||||||
|
if (event.data == 'KICK') {
|
||||||
|
console.log('Kick initiated.')
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/403';
|
||||||
|
}, 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedData = JSON.parse(event.data);
|
||||||
|
|
||||||
|
updatePanels(parsedData);
|
||||||
|
const sum = signalData.reduce((acc, strNum) => acc + parseFloat(strNum), 0);
|
||||||
|
const averageSignal = sum / signalData.length;
|
||||||
|
data.push(averageSignal);
|
||||||
|
}
|
||||||
|
// Attach the message handler
|
||||||
|
socket.onmessage = handleWebSocketMessage;
|
||||||
|
|
||||||
function initCanvas(parsedData) {
|
function initCanvas(parsedData) {
|
||||||
signalToggle = $("#signal-units-toggle");
|
signalToggle = $("#signal-units-toggle");
|
||||||
|
|
||||||
@@ -370,7 +423,7 @@ function updateCanvas(parsedData, signalChart) {
|
|||||||
|
|
||||||
socket.onmessage = (event) => {
|
socket.onmessage = (event) => {
|
||||||
if (event.data == 'KICK') {
|
if (event.data == 'KICK') {
|
||||||
console.log('Kick iniitiated.')
|
console.log('Kick initiated.')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.href = '/403';
|
window.location.href = '/403';
|
||||||
}, 500);
|
}, 500);
|
||||||
@@ -908,6 +961,11 @@ function initTooltips() {
|
|||||||
posX -= tooltipWidth / 2;
|
posX -= tooltipWidth / 2;
|
||||||
posY -= tooltipHeight + 10;
|
posY -= tooltipHeight + 10;
|
||||||
tooltip.css({ top: posY, left: posX, opacity: 1 }); // Set opacity to 1
|
tooltip.css({ top: posY, left: posX, opacity: 1 }); // Set opacity to 1
|
||||||
|
// For touchscreen devices
|
||||||
|
if ((/Mobi|Android|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) && ('ontouchstart' in window || navigator.maxTouchPoints)) {
|
||||||
|
setTimeout(() => { $('.tooltiptext').remove(); }, 10000);
|
||||||
|
document.addEventListener('touchstart', function() { setTimeout(() => { $('.tooltiptext').remove(); }, 500); });
|
||||||
|
}
|
||||||
}, 500));
|
}, 500));
|
||||||
}, function() {
|
}, function() {
|
||||||
// Clear the timeout if the mouse leaves before the delay completes
|
// Clear the timeout if the mouse leaves before the delay completes
|
||||||
|
|||||||
Reference in New Issue
Block a user