From e11ecdfcc35333921408d51bcbdd55ae6ca3bcec Mon Sep 17 00:00:00 2001 From: NoobishSVK Date: Sun, 18 Feb 2024 23:33:08 +0100 Subject: [PATCH] ui, rds changes, bugfixes --- datahandler.js | 39 ++++++++++++++++++++++++++++++--- package.json | 2 +- stream/parser.js | 2 +- tx_search.js | 13 ++++++----- web/css/modal.css | 3 ++- web/index.ejs | 15 ++++++++++--- web/js/main.js | 54 +++++++++++++++++++++++++++++----------------- web/js/settings.js | 22 +++++++++++++++++++ 8 files changed, 116 insertions(+), 34 deletions(-) diff --git a/datahandler.js b/datahandler.js index c57c0e6..858c9ca 100644 --- a/datahandler.js +++ b/datahandler.js @@ -204,9 +204,11 @@ const clientUpdateIntervals = new Map(); // Store update intervals for each clie // Initialize the data object var dataToSend = { pi: '?', - freq: 87.500.toFixed(3), + freq: 87.500, + previousFreq: 87.500, signal: 0, st: false, + st_forced: false, ps: '', tp: false, ta: 0, @@ -243,7 +245,6 @@ function handleData(ws, receivedData) { const currentTime = Date.now(); let modifiedData, parsedValue; const receivedLines = receivedData.split('\n'); - for (const receivedLine of receivedLines) { switch (true) { case receivedLine.startsWith('P'): @@ -261,6 +262,7 @@ function handleData(ws, receivedData) { parsedValue = parseFloat(modifiedData); if (!isNaN(parsedValue)) { + initialData.freq = (parsedValue / 1000).toFixed(3); dataToSend.freq = (parsedValue / 1000).toFixed(3); dataToSend.pi = '?'; } @@ -300,6 +302,9 @@ function handleData(ws, receivedData) { 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); @@ -310,13 +315,41 @@ function handleData(ws, receivedData) { 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); } 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); + } + 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; case receivedLine.startsWith('R'): modifiedData = receivedLine.slice(1); diff --git a/package.json b/package.json index 6e8de41..7668ff5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fm-dx-webserver", - "version": "1.0.6", + "version": "1.0.8", "description": "", "main": "index.js", "scripts": { diff --git a/stream/parser.js b/stream/parser.js index 3bc2c00..a4ac5a4 100644 --- a/stream/parser.js +++ b/stream/parser.js @@ -54,7 +54,7 @@ function parseAudioDevice(options, callback) { } }); } else { - console.log('No matches found.'); + logWarn('No audio devices have been found.'); } }); break; diff --git a/tx_search.js b/tx_search.js index bf9eb25..c154402 100644 --- a/tx_search.js +++ b/tx_search.js @@ -23,7 +23,7 @@ function fetchTx(freq, piCode, rdsPs) { return processData(cachedData[freq], piCode, rdsPs); } - const url = "https://maps.fmdx.pl/controller.php?freq=" + freq; + const url = "https://maps.fmdx.pl/api?freq=" + freq; return fetch(url) .then(response => response.json()) @@ -40,8 +40,9 @@ function fetchTx(freq, piCode, rdsPs) { function processData(data, piCode, rdsPs) { let matchingStation = null; let matchingCity = null; - let minDistance = Infinity; + let maxScore = -Infinity; // Initialize maxScore with a very low value let txAzimuth; + let maxDistance; for (const cityId in data.locations) { const city = data.locations[cityId]; @@ -49,11 +50,13 @@ function processData(data, piCode, rdsPs) { for (const station of city.stations) { if (station.pi === piCode && !station.extra && station.ps && station.ps.toLowerCase().includes(rdsPs.replace(/ /g, '_').replace(/^_*(.*?)_*$/, '$1').toLowerCase())) { const distance = haversine(serverConfig.identification.lat, serverConfig.identification.lon, city.lat, city.lon); - if (distance.distanceKm < minDistance) { - minDistance = distance.distanceKm; + const score = station.erp / distance.distanceKm; // Calculate score + if (score > maxScore) { + maxScore = score; txAzimuth = distance.azimuth; matchingStation = station; matchingCity = city; + maxDistance = distance.distanceKm; } } } @@ -67,7 +70,7 @@ function processData(data, piCode, rdsPs) { erp: matchingStation.erp, city: matchingCity.name, itu: matchingCity.itu, - distance: minDistance.toFixed(0), + distance: maxDistance.toFixed(0), azimuth: txAzimuth.toFixed(0), foundStation: true }; diff --git a/web/css/modal.css b/web/css/modal.css index ec2c0bd..bf9f877 100644 --- a/web/css/modal.css +++ b/web/css/modal.css @@ -94,10 +94,11 @@ .modal-panel-content { flex: 1; position: relative; + overflow-y: auto; } .modal-panel-content .version-info { - margin-top: 75px; + margin-top: 20px; width: 100%; } diff --git a/web/index.ejs b/web/index.ejs index cc422f2..17da0e6 100644 --- a/web/index.ejs +++ b/web/index.ejs @@ -229,10 +229,19 @@
  • dBm
  • - +
    +
    + + +
    +
    + + +
    +
    - + 0
    @@ -259,7 +268,7 @@

    FM-DX WebServer
    by Noobish & the OpenRadio community.

    - v1.0.6 [16/2/2024] + v1.0.7 [18/2/2024]

    librds & maps.fmdx.pl by Konrad Kosmatka
    3LAS by JoJoBond
    diff --git a/web/js/main.js b/web/js/main.js index 387cd5d..9a16824 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -2,9 +2,8 @@ var url = new URL('text', window.location.href); url.protocol = url.protocol.replace('http', 'ws'); var socketAddress = url.href; var socket = new WebSocket(socketAddress); -var parsedData; +var parsedData, signalChart, previousFreq; var data = []; -let signalChart; let updateCounter = 0; const europe_programmes = [ @@ -71,7 +70,8 @@ $(document).ready(function () { }); textInput.on('keyup', function (event) { - if (event.key !== 'Backspace') { + + if (event.key !== 'Backspace' && localStorage.getItem('extendedFreqRange') != "true") { let inputValue = textInput.val(); inputValue = inputValue.replace(/[^0-9.]/g, ''); @@ -174,17 +174,13 @@ function getInitialSettings() { } function getLocalizedTime(serverTime) { - // Convert server time to a Date object const serverDate = new Date(serverTime); - - // Calculate local time by adding the offset - const localTime = new Date(serverDate.getTime()); - - // Format local time + + // Format server time using options for local time formatting const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: false }; - const formattedLocalTime = localTime.toLocaleString(navigator.language ? navigator.language : 'en-US', options); + const formattedServerTime = serverDate.toLocaleString(navigator.language ? navigator.language : 'en-US', options); - return formattedLocalTime; + return formattedServerTime; } function getServerTime() { @@ -192,12 +188,8 @@ function getServerTime() { url: './server_time', dataType: 'json', success: function (data) { - // Convert server time to local time format - const localizedTimeServer = getLocalizedTime(data.serverTime); - const localizedTimeClient = getLocalizedTime(new Date().toISOString()); - - $('#server-time').text(localizedTimeServer); - $('#client-time').text(localizedTimeClient); + $('#server-time').text(getLocalizedTime(data.serverTime)); + $('#client-time').text(getLocalizedTime(new Date())); }, error: function (error) { console.error('Error:', error); @@ -389,6 +381,9 @@ function checkKey(e) { if (socket.readyState === WebSocket.OPEN) { switch (e.keyCode) { + case 66: // Back to previous frequency + socket.send("T" + (previousFreq * 1000)); + break; case 82: // RDS Reset (R key) socket.send("T" + (currentFreq.toFixed(1) * 1000)); break; @@ -408,6 +403,7 @@ function checkKey(e) { // Handle default case if needed break; } + previousFreq = currentFreq; } } @@ -571,6 +567,9 @@ function updateDataElements(parsedData) { $('#data-frequency').text(parsedData.freq); $("#commandinput").attr("aria-label", "Current frequency: " + parsedData.freq); $('#data-pi').html(parsedData.pi === '?' ? "?" : parsedData.pi); + if (localStorage.getItem('psUnderscores') === 'true') { + parsedData.ps = parsedData.ps.replace(/\s/g, '_'); + } $('#data-ps').html(parsedData.ps === '?' ? "?" : processString(parsedData.ps, parsedData.ps_errors)); $('.data-tp').html(parsedData.tp === false ? "TP" : "TP"); $('.data-ta').html(parsedData.ta === 0 ? "TA" : "TA"); @@ -582,15 +581,30 @@ function updateDataElements(parsedData) { ) ); $('.data-pty').html(europe_programmes[parsedData.pty]); - $('.data-st').html(parsedData.st === false ? "ST" : "ST"); + + + if(parsedData.st === true) { + if (parsedData.st_forced == true) { + $('.data-st').html("MO"); + } else { + $('.data-st').html("ST"); + } + } else { + if (parsedData.st_forced == true) { + $('.data-st').html("MO"); + } else { + $('.data-st').html("ST"); + } + } + console.log(parsedData.st, parsedData.st_forced); + $('#data-rt0').html(processString(parsedData.rt0, parsedData.rt0_errors)); $('#data-rt1').html(processString(parsedData.rt1, parsedData.rt1_errors)); $('.data-flag').html(``); $('#data-ant input').val($('#data-ant li[data-value="' + parsedData.ant + '"]').text()); if (parsedData.txInfo.station.length > 1) { - const sanitizedStation = parsedData.txInfo.station.replace(/%/g, '%25'); - $('#data-station-name').text(decodeURIComponent(sanitizedStation.replace(/\u009e/g, '\u017E'))); + $('#data-station-name').text(parsedData.txInfo.station.replace(/%/g, '%25')); $('#data-station-erp').text(parsedData.txInfo.erp); $('#data-station-city').text(parsedData.txInfo.city); $('#data-station-itu').text(parsedData.txInfo.itu); diff --git a/web/js/settings.js b/web/js/settings.js index a7a550d..66969ce 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -104,6 +104,28 @@ }); }); + var extendedFreqRange = localStorage.getItem("extendedFreqRange"); + if (extendedFreqRange === "true") { + $("#extended-frequency-range").prop("checked", true); + } + + // Save the value of the checkbox into local storage when its state changes + $("#extended-frequency-range").change(function() { + var isChecked = $(this).is(":checked"); + localStorage.setItem("extendedFreqRange", isChecked); + }); + + var extendedFreqRange = localStorage.getItem("psUnderscores"); + if (extendedFreqRange === "true") { + $("#ps-underscores").prop("checked", true); + } + + // Save the value of the checkbox into local storage when its state changes + $("#ps-underscores").change(function() { + var isChecked = $(this).is(":checked"); + localStorage.setItem("psUnderscores", isChecked); + }); + });