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 @@
FM-DX WebServer
by Noobish & the OpenRadio community.
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);
+ });
+
});