1
0
mirror of https://github.com/KubaPro010/fm-dx-webserver.git synced 2026-02-26 22:13:53 +01:00

device types, bugfixes

This commit is contained in:
NoobishSVK
2024-03-16 18:49:18 +01:00
parent aeb2361f77
commit 44e2927801
14 changed files with 288 additions and 118 deletions

View File

@@ -6,6 +6,7 @@ const path = require('path');
const os = require('os');
const platform = os.platform();
const cpuArchitecture = os.arch();
const { configName, serverConfig, configUpdate, configSave } = require('./server_config');
let unicode_type;
let shared_Library;
@@ -207,8 +208,10 @@ var dataToSend = {
freq: 87.500.toFixed(3),
previousFreq: 87.500.toFixed(3),
signal: 0,
highestSignal: -Infinity,
st: false,
st_forced: false,
rds: false,
ps: '',
tp: 0,
ta: 0,
@@ -234,6 +237,14 @@ var dataToSend = {
users: 0,
};
const filterMappings = {
'G11': { eq: 1, ims: 1 },
'G01': { eq: 0, ims: 1 },
'G10': { eq: 1, ims: 0 },
'G00': { eq: 0, ims: 0 }
};
var legacyRdsPiBuffer = null;
const initialData = { ...dataToSend };
const resetToDefault = dataToSend => Object.assign(dataToSend, initialData);
@@ -243,8 +254,10 @@ function handleData(ws, receivedData) {
// Retrieve the last update time for this client
let lastUpdateTime = clientUpdateIntervals.get(ws) || 0;
const currentTime = Date.now();
let modifiedData, parsedValue;
const receivedLines = receivedData.split('\n');
for (const receivedLine of receivedLines) {
switch (true) {
case receivedLine.startsWith('P'):
@@ -272,86 +285,29 @@ function handleData(ws, receivedData) {
initialData.ant = receivedLine.substring(1);
break;
case receivedLine.startsWith('G'):
switch (receivedLine) {
case 'G11':
initialData.eq = 1;
dataToSend.eq = 1;
initialData.ims = 1;
dataToSend.ims = 1;
break;
case 'G01':
initialData.eq = 0;
dataToSend.eq = 0;
initialData.ims = 1;
dataToSend.ims = 1;
break;
case 'G10':
initialData.eq = 1;
dataToSend.eq = 1;
initialData.ims = 0;
dataToSend.ims = 0;
break;
case 'G00':
initialData.eq = 0;
initialData.ims = 0;
dataToSend.eq = 0;
dataToSend.ims = 0;
break;
}
case receivedLine.startsWith('Sm'):
modifiedData = receivedLine.substring(2);
parsedValue = parseFloat(modifiedData);
dataToSend.st = false;
dataToSend.st_forced = false;
initialData.st = false;
initialData.st_forced = false;
if (!isNaN(parsedValue)) {
dataToSend.signal = parsedValue.toFixed(2);
initialData.signal = parsedValue.toFixed(2);
const mapping = filterMappings[receivedLine];
if (mapping) {
initialData.eq = mapping.eq;
initialData.ims = mapping.ims;
dataToSend.eq = mapping.eq;
dataToSend.ims = mapping.ims;
}
break;
case receivedData.startsWith('Sm'):
processSignal(receivedData, false, false);
break;
case receivedData.startsWith('Ss'):
modifiedData = receivedData.substring(2);
parsedValue = parseFloat(modifiedData);
dataToSend.st = true;
dataToSend.st_forced = false;
initialData.st = true;
initialData.st_forced = false;
if (!isNaN(parsedValue)) {
dataToSend.signal = parsedValue.toFixed(2);
initialData.signal = parsedValue.toFixed(2);
}
processSignal(receivedData, true, false);
break;
case receivedData.startsWith('SS'):
modifiedData = receivedData.substring(2);
parsedValue = parseFloat(modifiedData);
dataToSend.st = true;
dataToSend.st_forced = true;
initialData.st = true;
initialData.st_forced = true;
if (!isNaN(parsedValue)) {
dataToSend.signal = parsedValue.toFixed(2);
initialData.signal = parsedValue.toFixed(2);
}
processSignal(receivedData, true, true);
break;
case receivedData.startsWith('SM'):
modifiedData = receivedData.substring(2);
parsedValue = parseFloat(modifiedData);
dataToSend.st = false;
dataToSend.st_forced = true;
initialData.st = false;
initialData.st_forced = true;
if (!isNaN(parsedValue)) {
dataToSend.signal = parsedValue.toFixed(2);
initialData.signal = parsedValue.toFixed(2);
}
break;
processSignal(receivedData, false, true);
break;
case receivedLine.startsWith('R'):
modifiedData = receivedLine.slice(1);
dataToSend.rds = true;
if (modifiedData.length == 14) {
// Handle legacy RDS message
@@ -411,6 +367,42 @@ function showOnlineUsers(currentUsers) {
initialData.users = currentUsers;
}
function convertSignal(dBFS, fullScaleVoltage = 1, inputImpedance = 300) {
// Convert dBFS to voltage
let voltage = Math.pow(10, dBFS / 20) * fullScaleVoltage;
// Convert voltage to microvolts
let uV = voltage * 1e6;
// Convert microvolts to dBuV
let dBf = 20 * Math.log10(uV / Math.sqrt(2) / Math.sqrt(inputImpedance));
return dBf.toFixed(2);
}
function processSignal(receivedData, st, stForced) {
const modifiedData = receivedData.substring(2);
const parsedValue = parseFloat(modifiedData);
dataToSend.st = st;
dataToSend.st_forced = stForced;
initialData.st = st;
initialData.st_forced = stForced;
if (!isNaN(parsedValue)) {
/*if (serverConfig.device && serverConfig.device === 'sdr') {
dataToSend.signal = convertSignal(parsedValue);
initialData.signal = convertSignal(parsedValue);
} else {*/
dataToSend.signal = parsedValue.toFixed(2);
initialData.signal = parsedValue.toFixed(2);
//}
if(dataToSend.signal > dataToSend.highestSignal) {
dataToSend.highestSignal = dataToSend.signal;
}
}
}
module.exports = {
handleData, showOnlineUsers, dataToSend, initialData, resetToDefault
};

View File

@@ -2,7 +2,8 @@
const fs = require('fs');
const fetch = require('node-fetch');
const { logDebug, logError, logInfo, logWarn } = require('./console');
const { serverConfig, configUpdate, configSave } = require('./server_config')
const { serverConfig, configUpdate, configSave } = require('./server_config');
var pjson = require('./package.json');
let timeoutID = null;
@@ -59,6 +60,12 @@ function sendKeepalive() {
}
function sendUpdate() {
let bwLimit = '';
if (serverConfig.webserver.tuningLimit === true) {
bwLimit = serverConfig.webserver.tuningLowerLimit + ' - ' + serverConfig.webserver.tuningUpperLimit + ' Mhz';
}
const request = {
status: (serverConfig.lockToAdmin ? 2 : 1),
coords: [serverConfig.identification.lat, serverConfig.identification.lon],
@@ -66,7 +73,10 @@ function sendUpdate() {
desc: serverConfig.identification.tunerDesc,
audioChannels: serverConfig.audio.audioChannels,
audioQuality: serverConfig.audio.audioBitrate,
contact: serverConfig.identification.contact || ''
contact: serverConfig.identification.contact || '',
device: serverConfig.deviceName || '',
bwLimit: bwLimit,
version: pjson.version
};
if (serverConfig.identification.token)

View File

@@ -108,6 +108,8 @@ function connectToSerial() {
serialport.on('open', () => {
logInfo('Using COM device: ' + serverConfig.xdrd.comPort);
serialport.write('x\n');
serialport.write('M0\n');
serialport.write('Y100\n');
serialport.write('D0\n');
@@ -128,8 +130,6 @@ function connectToSerial() {
serialport.write('T87500\n');
}
serialport.write('x\n');
serialport.on('data', (data) => {
resolveDataBuffer(data);
});
@@ -422,6 +422,7 @@ app.get('/', (req, res) => {
tuningLowerLimit: serverConfig.webserver.tuningLowerLimit,
tuningUpperLimit: serverConfig.webserver.tuningUpperLimit,
chatEnabled: serverConfig.webserver.chatEnabled,
device: serverConfig.device
})
}
});
@@ -637,7 +638,7 @@ wss.on('connection', (ws, request) => {
}
}
if((serverConfig.publicTuner === true) || (request.session && request.session.isTuneAuthenticated === true && serverConfig.xdrd.wirelessConnection)) {
if((serverConfig.publicTuner === true) || (request.session && request.session.isTuneAuthenticated === true && serverConfig.xdrd.wirelessConnection)) {
if(serverConfig.lockToAdmin === true) {
if(request.session && request.session.isAdminAuthenticated === true) {

View File

@@ -1,6 +1,6 @@
{
"name": "fm-dx-webserver",
"version": "1.1.3",
"version": "1.1.4",
"description": "",
"main": "index.js",
"scripts": {

View File

@@ -10,6 +10,10 @@ const fetchInterval = 3000;
function fetchTx(freq, piCode, rdsPs) {
const now = Date.now();
freq = parseFloat(freq);
if(isNaN(freq)) {
return;
}
// Check if it's been at least 3 seconds since the last fetch and if the QTH is correct
if (now - lastFetchTime < fetchInterval || serverConfig.identification.lat.length < 2 || freq < 87) {
return Promise.resolve();

View File

@@ -36,6 +36,24 @@ h4 {
font-size: 20px;
}
.tooltip {
display: inline-block;
cursor: pointer;
}
.tooltiptext {
position: absolute;
background-color: var(--color-3);
color: var(--color-text);
text-align: center;
font-size: 14px;
border-radius: 30px;
padding: 5px 25px;
z-index: 1000;
opacity:var(--color-main);
transition: opacity 0.3s ease-in-out;
}
p#tuner-desc {
margin: 0;
}
@@ -78,6 +96,10 @@ label {
font-size: 20px;
}
.highest-signal-container {
margin-bottom: -20px !important;
}
.form-group {
float: left;
margin-bottom: 10px;
@@ -215,6 +237,17 @@ label {
#tuner-wireless {
display: none;
}
.overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
pointer-events: auto; /* Ensure that the overlay captures clicks */
opacity: 0; /* Make the overlay invisible */
}
@media (max-width: 768px) {
canvas, #flags-container {
display: none;
@@ -234,6 +267,10 @@ label {
.form-group {
float: none;
}
.highest-signal-container {
margin-top: -20px !important;
margin-bottom: 15px !important;
}
#data-pi {
font-size: 24px;
margin-top: 20px;

View File

@@ -202,6 +202,10 @@
display: none;
}
.user-select-none {
user-select: none;
}
@media only screen and (max-width: 960px) {
.text-medium-big {
font-size: 32px;

View File

@@ -6,6 +6,7 @@
<link href="css/flags.min.css" type="text/css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" type="text/css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="icon" type="image/png" href="favicon2.png" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -73,12 +74,12 @@
<div class="panel-10 no-bg h-100 m-0 m-right-20 hide-phone" style="width: 100px;margin-right: 20px !important;">
<button class="playbutton" aria-label="Play / Stop Button"><i class="fa-solid fa-play fa-lg"></i></button>
</div>
<div class="panel-100 m-0 hover-brighten flex-center" id="ps-container" style="height: 90px;">
<div class="panel-100 m-0 hover-brighten flex-center" id="ps-container" style="height: 90px;" data-tooltip="Clicking on the RDS PS will copy the RDS info into the clipboard.">
<span class="text-big" id="data-ps"></span>
</div>
</div>
<div id="flags-container-desktop" class="panel-33">
<div id="flags-container-desktop" class="panel-33 user-select-none">
<h2 class="show-phone">
<div class="data-pty text-color-default"></div>
</h2>
@@ -88,14 +89,17 @@
<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"><span style="margin-left: 20px;" class="data-st">ST</span></span>
<span id="stereo-container" class="pointer" style="position: relative;">
<span style="margin-left: 20px;" class="data-st">ST</span>
<span class="overlay" data-tooltip="Stereo / Mono toggle. <br><strong>Click to toggle."></span>
</span>
<span style="margin-left: 15px;" class="data-ms">MS</span>
</h3>
</div>
</div>
<div class="flex-container">
<div class="panel-33 hover-brighten" id="pi-code-container">
<div class="panel-33 hover-brighten" id="pi-code-container" data-tooltip="Clicking on the PI code will show the current station on a map.">
<h2>PI CODE</h2>
<span id="data-pi" class="text-big text-uppercase"></span>
</div>
@@ -107,11 +111,16 @@
<div class="panel-33">
<h2>SIGNAL</h2>
<span class="text-big">
<div class="text-small text-gray highest-signal-container">
<i class="fa-solid fa-arrow-up"></i>
<span id="data-signal-highest"></span>
<span class="signal-units"></span>
</div>
<div class="text-big">
<span id="data-signal"></span><!--
--><span id="data-signal-decimal" class="text-medium-big" style="opacity:0.7;"></span>
<span id="signal-units" class="text-medium">dBf</span>
</span>
<span class="signal-units text-medium">dBf</span>
</div>
</div>
</div>
@@ -135,10 +144,12 @@
<% } %>
<div class="panel-100 no-bg h-100 m-0 button-eq">
<button id="data-eq" style="border-radius: 30px 0px 0px 30px;" aria-label="EQ / RF+ Filter"><span class="text-bold">EQ</span><br><span class="text-smaller">(RF+)</span></button>
<% if (device == 'tef') { %><button id="data-eq" style="border-radius: 30px 0px 0px 30px;" aria-label="EQ Filter" data-tooltip="<strong>The cEQ filter can reduce bandwidth below 56 KHz.</strong><br><br>Useful for weak stations next to strong ones,<br>although it may pick up more interference."><span class="text-bold">cEQ</span></button><% } %>
<% if (device == 'xdr') { %><button id="data-eq" style="border-radius: 30px 0px 0px 30px;" aria-label="RF+ Filter" data-tooltip="<strong>The RF+ filter increases gain by 5dB</strong>"><span class="text-bold">RF+</span></button><% } %>
</div>
<div class="panel-100 no-bg h-100 m-0 button-ims">
<button id="data-ims" style="border-radius: 0px 30px 30px 0px;" aria-label="iMS / IF+ Filter"><span class="text-bold">iMS</span><br><span class="text-smaller">(IF+)</span></button>
<% if (device == 'tef') { %><button id="data-ims" style="border-radius: 0px 30px 30px 0px;" aria-label="iMS + Filter" data-tooltip="<strong>The iMS filter reduces multipath audio artifacts.</strong><br><br>It's recommended to leave it on most of the time."><span class="text-bold">iMS</span></button><% } %>
<% if (device == 'xdr') { %><button id="data-ims" style="border-radius: 0px 30px 30px 0px;" aria-label="IF+ Filter" data-tooltip="<strong>The IF+ filter increases gain by 6dB</strong>"><span class="text-bold">IF+</span></button><% } %>
</div>
</div>
</div>
@@ -162,7 +173,7 @@
<hr class="hide-desktop">
</div>
<div class="panel-33 hover-brighten">
<div class="panel-33 hover-brighten" data-tooltip="This panel contains the current TX info when RDS is loaded.<br><strong>Clicking on this panel copies the info into the clipboard.</strong>">
<div id="data-station-container">
<h2 style="margin-top: 0;" class="mb-0">
<span id="data-station-name"></span>
@@ -277,7 +288,7 @@
<a href="./setup">Setup</a> • <a class="logout-link" href="#">Logout</a>
</p>
<% } else if (isTuneAuthenticated) { %>
<p>You are logged in and can control the receiver. <a class="logout-link" href="#">Logout</a></p>
<p>You are logged in and can control the receiver.<br><a class="logout-link" href="#">Logout</a></p>
<% } else { %>
<form action="./login" method="post" id="login-form" class="top-25">
<label for="password">Password:</label>
@@ -349,5 +360,9 @@
</div>
<script src="js/webserver.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/screenshot-capture/2.0.0/screenshot-capture.min.js"></script>
</body>
</html>

View File

@@ -41,6 +41,10 @@ function submitData() {
return $(this).text() === $('#audio-quality').val();
}).data('value') || "192k");
const device = ($('.options .option').filter(function() {
return $(this).text() === $('#device-type').val();
}).data('value') || "tef");
const tunerName = $('#webserver-name').val() || 'FM Tuner';
const tunerDesc = $('#webserver-desc').val() || 'Default FM tuner description';
const broadcastTuner = $("#broadcast-tuner").is(":checked");
@@ -94,6 +98,7 @@ function submitData() {
tunePass,
adminPass,
},
device,
publicTuner,
lockToAdmin,
autoShutdown,
@@ -179,6 +184,12 @@ function submitData() {
$("#com-devices").val(selectedDevice.text());
}
$('#device-type').val(data.device);
var selectedDevice = $(".option[data-value='" + data.device + "']");
if (selectedDevice.length > 0) {
$("#device-type").val(selectedDevice.text());
}
$('#audio-devices').val(data.audio.audioDevice);
$('#audio-channels').val(data.audio.audioChannels);
var selectedChannels = $(".option[data-value='" + data.audio.audioChannels + "']");

View File

@@ -17,11 +17,17 @@ const europe_programmes = [
"Oldies Music", "Folk Music", "Documentary", "Alarm Test"
];
const usa_programmes = [
"No PTY", "News", "Information", "Sports", "Talk", "Rock", "Classic Rock",
"Adults Hits", "Soft Rock", "Top 40", "Country", "Oldies", "Soft Music",
"Nostalgia", "Jazz", "Classical", "Rhythm and Blues", "Soft Rhythm and Blues",
"Language", "Religious Music", "Religious Talk", "Personality", "Public", "College",
"Spanish Talk", "Spanish Music", "Hip Hop", "", "", "Weather", "Emergency Test", "Emergency"
];
$(document).ready(function () {
var canvas = $('#signal-canvas')[0];
var signalToggle = $("#signal-units-toggle");
canvas.width = canvas.parentElement.clientWidth;
canvas.height = canvas.parentElement.clientHeight;
@@ -135,10 +141,11 @@ $(document).ready(function () {
$(rtContainer).on("click", copyRt);
$(txContainer).on("click", copyTx);
$(piCodeContainer).on("click", findOnMaps);
$(stereoContainer).on("click", toggleForcedStereo);
$(document).on("click", "#stereo-container", toggleForcedStereo);
$(freqContainer).on("click", function () {
textInput.focus();
});
initTooltips();
});
function getServerTime() {
@@ -377,6 +384,27 @@ function checkKey(e) {
case 82: // RDS Reset (R key)
tuneTo(Number(currentFreq));
break;
case 83: // Screenshot (S key)
screenshotCapture.capture().then(function (dataUrl) {
// Create an input element to hold the data URL temporarily
var aux = $('<input>').attr({
type: 'text',
value: dataUrl
});
// Append the input element to the body, select its contents, and copy them to the clipboard
$('body').append(aux);
aux.select();
document.execCommand('copy');
aux.remove();
// Alert the user that the screenshot has been copied to the clipboard
alert('Screenshot copied to clipboard!');
}).catch(function (error) {
console.error('Error capturing screenshot:', error);
});
break;
case 38:
socket.send("T" + (Math.round(currentFreq*1000) + ((currentFreq > 30) ? 10 : 1)));
break;
@@ -465,7 +493,7 @@ async function copyPs() {
var ps = $('#data-ps').text();
var signal = $('#data-signal').text();
var signalDecimal = $('#data-signal-decimal').text();
var signalUnit = $('#signal-units').text();
var signalUnit = $('.signal-units').text();
try {
await copyToClipboard(frequency + " - " + pi + " | " + ps + " [" + signal + signalDecimal + " " + signalUnit + "]");
@@ -543,13 +571,14 @@ function findOnMaps() {
function updateSignalUnits(parsedData, averageSignal) {
const signalUnit = localStorage.getItem('signalUnit');
let currentSignal;
let highestSignal = parsedData.highestSignal;
if(localStorage.getItem("smoothSignal") == 'true') {
currentSignal = averageSignal
} else {
currentSignal = parsedData.signal;
}
let signalText = $('#signal-units');
let signalText = $('.signal-units');
let signalValue;
switch (signalUnit) {
@@ -572,6 +601,7 @@ function updateSignalUnits(parsedData, averageSignal) {
const formatted = (Math.round(signalValue * 10) / 10).toFixed(1);
const [integerPart, decimalPart] = formatted.split('.');
$('#data-signal-highest').text(Number(highestSignal).toFixed(1));
$('#data-signal').text(integerPart);
$('#data-signal-decimal').text('.' + decimalPart);
}
@@ -589,6 +619,7 @@ function updateDataElements(parsedData) {
const $dataTp = $('.data-tp');
const $dataTa = $('.data-ta');
const $dataMs = $('.data-ms');
const $flagDesktopCointainer = $('#flags-container-desktop');
const $dataPty = $('.data-pty');
$dataFrequency.text(parsedData.freq);
@@ -604,6 +635,12 @@ function updateDataElements(parsedData) {
$dataRt1.html(processString(parsedData.rt1, parsedData.rt1_errors));
$dataPty.html(europe_programmes[parsedData.pty]);
if(parsedData.rds === true) {
$flagDesktopCointainer.css('background-color', 'var(--color-2');
} else {
$flagDesktopCointainer.css('background-color', 'var(--color-1');
}
$('.data-flag').html(`<i title="${parsedData.country_name}" class="flag-sm flag-sm-${parsedData.country_iso}"></i>`);
$('.data-flag-big').html(`<i title="${parsedData.country_name}" class="flag-md flag-md-${parsedData.country_iso}"></i>`);
@@ -719,4 +756,28 @@ function toggleForcedStereo() {
var message = "B";
message += parsedData.st_forced = (parsedData.st_forced == "1") ? "0" : "1";
socket.send(message);
}
function initTooltips() {
$('[data-tooltip]').hover(function(e){
var tooltipText = $(this).data('tooltip');
var tooltip = $('<div class="tooltiptext"></div>').html(tooltipText);
$('body').append(tooltip);
var tooltipWidth = tooltip.outerWidth();
var tooltipHeight = tooltip.outerHeight();
var posX = e.pageX - tooltipWidth / 2;
var posY = e.pageY - tooltipHeight - 10;
tooltip.css({ top: posY, left: posX, opacity: 0.9 });
}, function() {
$('.tooltiptext').remove();
}).mousemove(function(e){
var tooltipWidth = $('.tooltiptext').outerWidth();
var tooltipHeight = $('.tooltiptext').outerHeight();
var posX = e.pageX - tooltipWidth / 2;
var posY = e.pageY - tooltipHeight - 10;
$('.tooltiptext').css({ top: posY, left: posX });
});
}

View File

@@ -3,7 +3,7 @@ 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.3 [' + formattedDate + ']';
var currentVersion = 'v1.1.4 [' + formattedDate + ']';
/**

View File

@@ -48,13 +48,13 @@ function updateWizardContent() {
$('.btn-prev').show();
}
if($('.step:visible').index() == 2) {
if($('.step:visible').index() == 3) {
setTimeout(function () {
map.invalidateSize();
}, 200);
}
if($('.step:visible').index() == 3) {
if($('.step:visible').index() == 4) {
$('.btn-next').text('Save');
} else {
$('.btn-next').text('Next')

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>FM-DX Webserver</title>
<title>Setup - FM-DX Webserver</title>
<link href="css/entry.css" type="text/css" rel="stylesheet">
<link href="css/flags.min.css" type="text/css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" type="text/css" rel="stylesheet">
@@ -21,6 +21,7 @@
<div class="panel-100">
<ul class="nav">
<li data-panel="dashboard" class="active">Dashboard</li>
<li data-panel="tuner">Tuner</li>
<li data-panel="connection">Connection</li>
<li data-panel="audio">Audio</li>
<li data-panel="webserver">Webserver</li>
@@ -340,6 +341,21 @@
</div>
</div>
<div class="panel-100 tab-content" id="tuner">
<h2>Tuner Specific Settings</h2>
<div class="form-group">
<label for="themes"><i class="fa-solid fa-radio"></i> Device:</label>
<div class="dropdown" id="device-selector" style="margin-right: 0;">
<input type="text" placeholder="TEF6686 / TEA685x" id="device-type" readonly>
<ul class="options">
<li class="option" data-value="tef">TEF668x / TEA685x</li>
<li class="option" data-value="xdr">XDR (F1HD / S10HDiP)</li>
<li class="option" data-value="sdr">SDR (RTL-SDR / AirSpy)</li>
</ul>
</div>
</div>
</div>
<div class="panel-100 tab-content" id="identification">
<h2>Identification & Map</h2>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>FM-DX Webserver</title>
<title>Wizard - FM-DX Webserver</title>
<link href="css/entry.css" type="text/css" rel="stylesheet">
<link href="css/flags.min.css" type="text/css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" type="text/css" rel="stylesheet">
@@ -16,7 +16,6 @@
<% if (isAdminAuthenticated) { %>
<div class="panel-100 no-bg">
<img class="top-10" src="../images/openradio_logo_neutral.png" height="64px">
<h1 class="top-10">FM-DX WebServer</h1>
<h2 class="text-monospace text-light text-gray">[SETUP WIZARD]</h2>
</div>
<div class="panel-100 no-bg flex-container flex-center flex-phone">
@@ -24,14 +23,48 @@
<div class="btn-rounded-cube">2</div>
<div class="btn-rounded-cube">3</div>
<div class="btn-rounded-cube">4</div>
<div class="btn-rounded-cube">5</div>
</div>
<div class="panel-100">
<!-- BASIC SETTINGS -->
<div class="panel-100 step" id="step1">
<h2 class="settings-heading">BASIC SETTINGS</h2>
<h2 class="settings-heading">Basic settings</h2>
<p class="m-0">Welcome to the setup wizard! Let's set up some basic things.</p>
<h3>Webserver connection:</h3>
<p class="m-0 text-gray">Leave the IP at 0.0.0.0 unless you explicitly know you have to change it.<br>Don't enter your public IP here.</p>
<div class="flex-center top-25">
<div class="form-group">
<label for="webserver-ip">Webserver IP:</label>
<input class="input-text w-150" type="text" name="webserver-ip" id="webserver-ip" placeholder="0.0.0.0">
</div>
<div class="form-group">
<label for="webserver-port">Webserver port:</label>
<input class="input-text w-100" type="text" name="webserver-port" id="webserver-port" placeholder="8080">
</div>
</div>
</div>
<!-- BASIC SETTINGS END -->
<!-- TUNER SETTINGS -->
<div id="step2" class="step" style="display: none">
<h2>Tuner settings</h2>
<h3>Tuner type:</h3>
<p class="text-gray">Settings a proper device type ensures that the correct interface and settings will load.</p>
<div class="form-group">
<label for="themes"><i class="fa-solid fa-radio"></i> Device:</label>
<div class="dropdown" id="device-selector" style="margin-right: 0;">
<input type="text" placeholder="TEF6686 / TEA685x" id="device-type" readonly>
<ul class="options">
<li class="option" data-value="tef">TEF668x / TEA685x</li>
<li class="option" data-value="xdr">XDR (F1HD / S10HDiP)</li>
<li class="option" data-value="sdr">SDR (RTL-SDR / AirSpy)</li>
</ul>
</div>
</div>
<h3>Tuner connection:</h3>
<div style="width: 300px;" class="auto top-10">
<label class="toggleSwitch nolabel" onclick="">
@@ -74,24 +107,10 @@
</div>
</div>
</div>
<br class="top-25">
<h3>Webserver connection:</h3>
<p class="m-0 text-gray">Leave the IP at 0.0.0.0 unless you explicitly know you have to change it.<br>Don't enter your public IP here.</p>
<div class="flex-center top-25">
<div class="form-group">
<label for="webserver-ip">Webserver IP:</label>
<input class="input-text w-150" type="text" name="webserver-ip" id="webserver-ip" placeholder="0.0.0.0">
</div>
<div class="form-group">
<label for="webserver-port">Webserver port:</label>
<input class="input-text w-100" type="text" name="webserver-port" id="webserver-port" placeholder="8080">
</div>
</div>
</div>
<!-- BASIC SETTINGS END -->
<!-- TUNER SETTINGS END -->
<!-- AUDIO SETTINGS -->
<div id="step2" class="step" style="display: none;">
<div id="step3" class="step" style="display: none;">
<div class="panel-100" style="min-height: 120px;margin-bottom: 0;">
<h2 class="settings-heading">AUDIO SETTINGS</h2>
<p class="m-0 text-gray">In this section, we will set up the audio.<br>
@@ -143,7 +162,7 @@
</div>
<!-- AUDIO SETTINGS END -->
<!-- IDENTIFICATION START -->
<div id="step3" class="step" style="display: none;">
<div id="step4" class="step" style="display: none;">
<div class="panel-100" style="padding-bottom: 20px;">
<h2 class="settings-heading">IDENTIFICATION INFO</h2>
<p class="text-gray">In this part, we will set up your indentification info, such as the server name, description and location.</p>
@@ -188,7 +207,7 @@
</div>
<!-- IDENTIFICATION END -->
<!-- ADMIN SETTINGS START -->
<div id="step4" class="step" style="display: none;">
<div id="step5" class="step" style="display: none;">
<h2 class="settings-heading">Admin panel settings</h2>
<p>We are at the last and final step of the settings.</p>