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

cleaner command system + phone UI changes + iMS/EQ

This commit is contained in:
NoobishSVK
2024-01-28 14:37:32 +01:00
parent 8eb63eb5c4
commit 66892cedbe
10 changed files with 318 additions and 105 deletions

View File

@@ -198,6 +198,8 @@ var dataToSend = {
af: [],
rt0: '',
rt1: '',
ims: 0,
eq: 0,
country_name: '',
country_iso: 'UN',
users: '',
@@ -235,6 +237,32 @@ function handleData(ws, receivedData) {
dataToSend.pi = '?';
}
break;
case receivedLine.startsWith('G'):
if(receivedLine === 'G11') {
initialData.eq = 1;
initialData.ims = 1;
dataToSend.eq = 1;
dataToSend.ims = 1;
}
if(receivedLine === 'G01') {
initialData.eq = 0;
initialData.ims = 1;
dataToSend.eq = 0;
dataToSend.ims = 1;
}
if(receivedLine === 'G10') {
initialData.eq = 1;
initialData.ims = 0;
dataToSend.eq = 1;
dataToSend.ims = 0;
}
if(receivedLine === 'G00') {
initialData.eq = 0;
initialData.ims = 0;
dataToSend.eq = 0;
dataToSend.ims = 0;
}
break;
case receivedLine.startsWith('Sm'):
modifiedData = receivedLine.substring(2);

View File

@@ -9,7 +9,7 @@ const path = require('path');
const net = require('net');
const client = new net.Socket();
const crypto = require('crypto');
const commandExists = require('command-exists-promise')
const commandExists = require('command-exists-promise');
const dataHandler = require('./datahandler');
const consoleCmd = require('./console');
const config = require('./userconfig');
@@ -46,8 +46,8 @@ wss.on('connection', (ws, request) => {
ws.on('message', (message) => {
logDebug('Received message from client:', message.toString());
newFreq = message.toString() * 1000;
client.write("T" + newFreq + '\n');
command = message.toString();
client.write(command + "\n");
});
ws.on('close', (code, reason) => {
@@ -112,6 +112,8 @@ client.connect(xdrdServerPort, xdrdServerHost, () => {
if (authFlags.authMsg && authFlags.firstClient) {
client.write('T87500\n');
client.write('A0\n');
client.write('G11\n');
client.off('data', authDataHandler);
return;
}

View File

@@ -7,7 +7,7 @@ const audioPort = 8081;
const xdrdServerHost = '127.0.0.1'; // xdrd server IP (if it's running on the same machine, use 127.0.0.1)
const xdrdServerPort = 7373; // xdrd server port
const xdrdPassword = ''; // xdrd password (optional)
const xdrdPassword = 'password'; // xdrd password (optional)
const qthLatitude = ''; // your latitude, useful for maps.fmdx.pl integration
const qthLongitude = ''; // your longitude, useful for maps.fmdx.pl integration

View File

@@ -49,4 +49,69 @@ h3 {
font-size: 14px;
max-height: 380px;
overflow-y: auto;
}
}
#af-list a {
cursor: pointer;
}
#flags-container-phone {
display: none;
}
@media (max-width: 960px) {
canvas, #flags-container {
display: none;
}
#ps-container {
background-color: var(--color-1);
height: 100px !important;
}
h2 {
display: none;
}
#data-pi {
font-size: 24px;
margin-top: 50px;
color: #aaa;
}
h2.show-phone {
display: inline;
padding: 0 !important;
}
#data-ps {
font-size: 60px;
}
#data-frequency {
font-size: 72px;
}
#data-rt0, #data-rt1 {
font-size: 10px;
text-align: left;
width: 100%;
}
#rt-container {
height: 32px !important;
}
ul {
font-size: 16px;
}
ul li {
display: inline;
margin-right: 5px;
}
li:not(:last-child)::after {
content: " •";
color: #aaa;
}
#flags-container-desktop {
display: none;
}
#flags-container-phone {
display: block;
}
#tune-buttons {
height: 64px;
}
}

View File

@@ -1,4 +1,4 @@
.play-button {
button {
width: 100%;
height: 100%;
border: 0;
@@ -6,9 +6,10 @@
transition: 0.3s ease-in-out background-color;
background-color: var(--color-4);
cursor: pointer;
font-family: inherit;
}
.play-button:hover {
button:hover {
background-color: var(--color-main-bright);
}

View File

@@ -2,6 +2,6 @@
@import url("main.css"); /* Root stuff that affects the entire webpage (body, wrapper etc.) */
@import url("breadcrumbs.css"); /* Stuff that applies to random elements only once/twice */
@import url("buttons.css"); /* Buttons, inputs, select boxes, checkboxes... */
@import url("helpers.css"); /* Stuff that is used often such as text changers etc */
@import url("panels.css"); /* Different panels and their sizes */
@import url("modal.css"); /* Modal window */
@import url("modal.css"); /* Modal window */
@import url("helpers.css"); /* Stuff that is used often such as text changers etc */

View File

@@ -6,6 +6,10 @@
background: #100d1f;
}
.bg-gray {
background: #999;
}
.bg-none {
background: transparent !important;
}
@@ -30,6 +34,22 @@
border-radius: 5px;
}
.m-0 {
margin: 0;
}
.m-left-20 {
margin-left: 20px;
}
.h-100 {
height: 100%;
}
.no-bg {
background-color: transparent;
}
.flex-container {
display: flex;
}
@@ -81,6 +101,10 @@
font-size: 11px;
}
.text-bold {
font-weight: bold;
}
.text-gray {
color: #666;
}
@@ -130,4 +154,7 @@
.flex-phone {
display: flex;
}
.hide-phone {
display: none;
}
}

View File

@@ -48,5 +48,12 @@
margin: auto;
width: 90%;
margin-bottom: 20px;
background-color: transparent;
}
.flex-phone {
display: flex;
}
.panel-90 {
margin-top: 100px;
}
}

View File

@@ -53,18 +53,18 @@
<span class="text-big" id="data-ps"></span>
</div>
<div class="panel-33">
<h2>
<div id="data-pty" style="color:white;"></div>
<div id="flags-container-desktop" class="panel-33">
<h2 class="show-phone">
<div class="data-pty" style="color:white;"></div>
</h2>
<h3 style="margin-top:0;margin-bottom:0;" class="flex-center">
<span id="data-tp" class="color-4">TP</span>
<span style="margin-left: 15px;" id="data-ta" class="color-4">TA</span>
<span class="data-tp color-4">TP</span>
<span style="margin-left: 15px;" class="data-ta color-4">TA</span>
<div style="display:inline-block">
<span style="margin-left: 20px;display: block;margin-top: 2px;" id="data-flag"></span>
<span style="margin-left: 20px;display: block;margin-top: 2px;" class="data-flag"></span>
</div>
<span style="margin-left: 20px; color: #ff5776;" id="data-st"></span>
<span style="margin-left: 15px;" id="data-ms"><span style="color: #ff5776">M</span><span class="text-gray">S</span></span>
<span style="margin-left: 20px; color: #ff5776;" class="data-st"></span>
<span style="margin-left: 15px;" class="data-ms"><span style="color: #ff5776">M</span><span class="text-gray">S</span></span>
</h3>
</div>
</div>
@@ -91,8 +91,18 @@
</div>
<div class="flex-container">
<div class="panel-33" style="height: 48px;">
<button id="playbutton" class="play-button"><i class="fa-solid fa-play"></i></button>
<div class="panel-33 no-bg" style="height: 48px;">
<div class="flex-container flex-phone h-100">
<div class="panel-75 no-bg h-100 m-0">
<button id="playbutton"><i class="fa-solid fa-play"></i></button>
</div>
<div class="panel-33 no-bg h-100 m-0 m-left-20">
<button id="data-eq" style="border-radius: 30px 0px 0px 30px;"><span class="text-bold">EQ</span><br><span class="text-smaller">(IF+)</span></button>
</div>
<div class="panel-33 no-bg h-100 m-0">
<button id="data-ims" style="border-radius: 0px 30px 30px 0px;"><span class="text-bold">iMS</span><br><span class="text-smaller">(RF+)</span></button>
</div>
</div>
</div>
<div class="panel-33 flex-container flex-phone" id="tune-buttons" style="opacity: 1;">
@@ -101,16 +111,8 @@
<button id="freq-up"><i class="fa-solid fa-chevron-right"></i></button>
</div>
<div class="panel-33" style="height: 48px;">
<div class="panel-33 hide-phone" style="height: 48px;">
<input type="range" id="volumeSlider" min="0" max="1" step="0.01" value="1">
<!--<label class="toggleSwitch nolabel" onclick="">
<input id="signal-units-toggle" type="checkbox"/>
<a></a>
<span>
<span class="left-span">dBf</span>
<span class="right-span">dBµV</span>
</span>
</label>-->
</div>
</div>
@@ -124,7 +126,7 @@
<div class="panel-33">
<h2>
<div id="data-pty" style="color:white;"></div>
<div style="color:white;"></div>
</h2>
<h3 style="margin-top:0;" class="flex-center">
</h3>
@@ -144,6 +146,20 @@
</div>
</div>
</div>
<div id="flags-container-phone" class="panel-33">
<h2 class="show-phone">
<div class="data-pty" style="color:white;"></div>
</h2>
<h3 style="margin-top:0;margin-bottom:0;" class="flex-center">
<span class="data-tp color-4">TP</span>
<span style="margin-left: 15px;" class="data-ta color-4">TA</span>
<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; color: #ff5776;" class="data-st"></span>
<span style="margin-left: 15px;" class="data-ms"><span style="color: #ff5776">M</span><span class="text-gray">S</span></span>
</h3>
</div>
</div>
<button id="settings"><i class="fa-solid fa-gear"></i></button>

View File

@@ -3,7 +3,7 @@ var hostname = hostParts[0]; // Extract the hostname
var port = hostParts[1] || '8080'; // Extract the port or use a default (e.g., 8080)
var socketAddress = 'ws://' + hostname + ':' + port + '/text'; // Use 'wss' for secure WebSocket connections (recommended for external access)
var socket = new WebSocket(socketAddress);
var parsedData;
const europe_programmes = [
"No PTY", "News", "Current Affairs", "Info",
@@ -42,8 +42,8 @@ $(document).ready(function() {
// Modify the WebSocket onmessage callback
socket.onmessage = (event) => {
const parsedData = JSON.parse(event.data);
parsedData = JSON.parse(event.data);
updatePanels(parsedData);
// Push the new signal data to the array
data.push(parsedData.signal);
@@ -117,71 +117,6 @@ $(document).ready(function() {
};
requestAnimationFrame(updateCanvas);
}
function updatePanels(parsedData) {
const sortedAf = parsedData.af.sort(compareNumbers);
const scaledArray = sortedAf.map(element => element / 1000);
const listContainer = $('#af-list');
const scrollTop = listContainer.scrollTop();
let ul = listContainer.find('ul');
if (!ul.length) {
ul = $('<ul></ul>');
listContainer.append(ul);
}
ul.html('');
const listItems = scaledArray.map(element => {
return $('<li></li>').text(element.toFixed(1))[0];
});
ul.append(listItems);
listContainer.scrollTop(scrollTop);
$('#data-frequency').text(parsedData.freq);
$('#data-pi').html(parsedData.pi === '?' ? "<span class='text-gray'>?</span>" : parsedData.pi);
$('#data-ps').html(parsedData.ps === '?' ? "<span class='text-gray'>?</span>" : processString(parsedData.ps, parsedData.ps_errors));
$('#data-tp').html(parsedData.tp === false ? "<span class='text-gray'>TP</span>" : "TP");
$('#data-ta').html(parsedData.ta === 0 ? "<span class='text-gray'>TA</span>" : "TA");
$('#data-ms').html(parsedData.ms === 0
? "<span class='text-gray'>M</span><span class='text-red'>S</span>"
: (parsedData.ms === -1
? "<span class='text-gray'>M</span><span class='text-gray'>S</span>"
: "<span class='text-red'>M</span><span class='text-gray'>S</span>"
)
);
$('#data-pty').html(europe_programmes[parsedData.pty]);
$('#data-st').html(parsedData.st === false ? "<span class='text-gray'>ST</span>" : "ST");
$('#data-rt0').html(processString(parsedData.rt0, parsedData.rt0_errors));
$('#data-rt1').html(processString(parsedData.rt1, parsedData.rt1_errors));
$('#data-flag').html('<i title="' + parsedData.country_name + '" class="flag-sm flag-sm-' + parsedData.country_iso + '"></i>');
const signalUnit = localStorage.getItem('signalUnit');
let signalText = $('#signal-units');
let signalValue;
switch (signalUnit) {
case 'dbuv':
signalValue = parsedData.signal - 11.25;
signalText.text('dBµV');
break;
case 'dbm':
signalValue = parsedData.signal - 120;
signalText.text('dBm');
break;
default:
signalValue = parsedData.signal;
signalText.text('dBf');
break;
}
const integerPart = Math.floor(signalValue);
const decimalPart = (signalValue - integerPart).toFixed(1).slice(1); // Adjusted this line
$('#data-signal').text(integerPart);
$('#data-signal-decimal').text(decimalPart);
$('#users-online').text(parsedData.users);
}
signalToggle.on("change", function() {
const signalText = localStorage.getItem('signalUnit');
@@ -201,7 +136,7 @@ $(document).ready(function() {
const inputValue = textInput.val();
// Check if the user agent contains 'iPhone'
if (/iPhone/i.test(navigator.userAgent) && socket.readyState === WebSocket.OPEN) {
socket.send(inputValue);
socket.send("T" + (inputValue * 1000));
// Clear the input field if needed
textInput.val('');
}
@@ -230,7 +165,7 @@ $(document).ready(function() {
if (event.key === 'Enter') {
const inputValue = textInput.val();
if (socket.readyState === WebSocket.OPEN) {
socket.send(inputValue);
socket.send("T" + (inputValue * 1000));
}
textInput.val('');
}
@@ -259,6 +194,14 @@ $(document).ready(function() {
var piCodeContainer = $('#pi-code-container')[0];
var freqContainer = $('#freq-container')[0];
$("#data-eq").click(function () {
toggleButtonState("eq");
});
$("#data-ims").click(function () {
toggleButtonState("ims");
});
$(freqUpButton).on("click", tuneUp);
$(freqDownButton).on("click", tuneDown);
$(psContainer).on("click", copyPs);
@@ -333,16 +276,16 @@ function checkKey(e) {
if (socket.readyState === WebSocket.OPEN) {
if (e.keyCode == '38') {
socket.send((currentFreq + 0.01).toFixed(2));
socket.send("T" + ((currentFreq + 0.01).toFixed(2) * 1000));
}
else if (e.keyCode == '40') {
socket.send((currentFreq - 0.01).toFixed(2));
socket.send("T" + ((currentFreq - 0.01).toFixed(2) * 1000));
}
else if (e.keyCode == '37') {
socket.send((currentFreq - 0.10).toFixed(1));
socket.send("T" + ((currentFreq - 0.10).toFixed(1) * 1000));
}
else if (e.keyCode == '39') {
socket.send((currentFreq + 0.10).toFixed(1));
socket.send("T" + ((currentFreq + 0.10).toFixed(1) * 1000));
}
}
}
@@ -350,14 +293,20 @@ function checkKey(e) {
function tuneUp() {
if (socket.readyState === WebSocket.OPEN) {
getCurrentFreq();
socket.send((currentFreq + 0.10).toFixed(1));
socket.send("T" + ((currentFreq + 0.10).toFixed(1) * 1000));
}
}
function tuneDown() {
if (socket.readyState === WebSocket.OPEN) {
getCurrentFreq();
socket.send((currentFreq - 0.10).toFixed(1));
socket.send("T" + ((currentFreq - 0.10).toFixed(1) * 1000));
}
}
function tuneTo(freq) {
if (socket.readyState === WebSocket.OPEN) {
socket.send("T" + ((freq).toFixed(1) * 1000));
}
}
@@ -424,4 +373,122 @@ function findOnMaps() {
var url = "https://maps.fmdx.pl/#qth=" + longitude + "," + latitude + "&freq=" + frequency + "&pi=" + pi;
window.open(url, "_blank");
}
function updateSignalUnits(parsedData) {
const signalUnit = localStorage.getItem('signalUnit');
let signalText = $('#signal-units');
let signalValue;
switch (signalUnit) {
case 'dbuv':
signalValue = parsedData.signal - 11.25;
signalText.text('dBµV');
break;
case 'dbm':
signalValue = parsedData.signal - 120;
signalText.text('dBm');
break;
default:
signalValue = parsedData.signal;
signalText.text('dBf');
break;
}
const integerPart = Math.floor(signalValue);
const decimalPart = (signalValue - integerPart).toFixed(1).slice(1);
$('#data-signal').text(integerPart);
$('#data-signal-decimal').text(decimalPart);
}
function updateDataElements(parsedData) {
$('#data-frequency').text(parsedData.freq);
$('#data-pi').html(parsedData.pi === '?' ? "<span class='text-gray'>?</span>" : parsedData.pi);
$('#data-ps').html(parsedData.ps === '?' ? "<span class='text-gray'>?</span>" : processString(parsedData.ps, parsedData.ps_errors));
$('.data-tp').html(parsedData.tp === false ? "<span class='text-gray'>TP</span>" : "TP");
$('.data-ta').html(parsedData.ta === 0 ? "<span class='text-gray'>TA</span>" : "TA");
$('.data-ms').html(parsedData.ms === 0
? "<span class='text-gray'>M</span><span class='text-red'>S</span>"
: (parsedData.ms === -1
? "<span class='text-gray'>M</span><span class='text-gray'>S</span>"
: "<span class='text-red'>M</span><span class='text-gray'>S</span>"
)
);
$('.data-pty').html(europe_programmes[parsedData.pty]);
$('.data-st').html(parsedData.st === false ? "<span class='text-gray'>ST</span>" : "ST");
$('#data-rt0').html(processString(parsedData.rt0, parsedData.rt0_errors));
$('#data-rt1').html(processString(parsedData.rt1, parsedData.rt1_errors));
$('.data-flag').html(`<i title="${parsedData.country_name}" class="flag-sm flag-sm-${parsedData.country_iso}"></i>`);
}
let isEventListenerAdded = false;
let updateCounter = 0;
function updatePanels(parsedData) {
updateCounter++;
const sortedAf = parsedData.af.sort(compareNumbers);
const scaledArray = sortedAf.map(element => element / 1000);
const listContainer = $('#af-list');
const scrollTop = listContainer.scrollTop();
let ul = listContainer.find('ul');
if (!ul.length) {
ul = $('<ul></ul>');
listContainer.append(ul);
}
if (updateCounter % 3 === 0) {
updateButtonState("data-eq", parsedData.eq);
updateButtonState("data-ims", parsedData.ims);
// Only update #af-list on every 3rd call
ul.html('');
const listItems = scaledArray.map(createListItem);
ul.append(listItems);
// Add the event listener only once
if (!isEventListenerAdded) {
ul.on('click', 'a', function () {
const frequency = parseFloat($(this).text());
tuneTo(frequency);
});
isEventListenerAdded = true;
}
listContainer.scrollTop(scrollTop);
}
// Update other elements every time
updateDataElements(parsedData);
updateSignalUnits(parsedData);
$('#users-online').text(parsedData.users);
}
function createListItem(element) {
return $('<li></li>').html(`<a>${element.toFixed(1)}</a>`)[0];
}
function updateButtonState(buttonId, value) {
var button = $("#" + buttonId);
if (value === 0) {
button.addClass("bg-gray");
} else {
button.removeClass("bg-gray");
}
}
function toggleButtonState(buttonId) {
parsedData[buttonId] = 1 - parsedData[buttonId]; // Toggle between 0 and 1
updateButtonState(buttonId, parsedData[buttonId]);
var message = "G";
message += parsedData.eq ? "1" : "0";
message += parsedData.ims ? "1" : "0";
socket.send(message);
}