$(document).ready(function() {
var hostParts = window.location.host.split(':');
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 dataContainer = $('#data-container');
var canvas = $('#signal-canvas')[0];
var context = canvas.getContext('2d');
var signalToggle = $("#signal-units-toggle");
canvas.width = canvas.parentElement.clientWidth;
var data = [];
var maxDataPoints = 250;
var pointWidth = (canvas.width - 80) / maxDataPoints;
var europe_programmes = [
"No PTY", "News", "Current Affairs", "Info",
"Sport", "Education", "Drama", "Culture", "Science", "Varied",
"Pop M", "Rock M", "Easy Listening", "Light Classical",
"Serious Classical", "Other Music", "Weather", "Finance",
"Children's Programmes", "Social Affairs", "Religion", "Phone-in",
"Travel", "Leisure", "Jazz Music", "Country Music", "National Music",
"Oldies Music", "Folk Music", "Documentary", "Alarm Test"
];
function getInitialSettings() {
$.ajax({
url: '/static_data',
dataType: 'json',
success: function(data) {
// Use the received data (data.qthLatitude, data.qthLongitude) as needed
localStorage.setItem('qthLatitude', data.qthLatitude);
localStorage.setItem('qthLongitude', data.qthLongitude);
localStorage.setItem('webServerName', data.webServerName);
document.title = 'FM-DX Webserver [' + data.webServerName + ']';
},
error: function(error) {
console.error('Error:', error);
}
});
}
getInitialSettings();
// Start updating the canvas
updateCanvas();
function updateCanvas() {
const color2 = getComputedStyle(document.documentElement).getPropertyValue('--color-2').trim();
const color4 = getComputedStyle(document.documentElement).getPropertyValue('--color-4').trim();
while (data.length >= maxDataPoints) {
data.shift();
}
// Modify the WebSocket onmessage callback
socket.onmessage = (event) => {
const parsedData = JSON.parse(event.data);
updatePanels(parsedData);
// Push the new signal data to the array
data.push(parsedData.signal);
const actualLowestValue = Math.min(...data);
const actualHighestValue = Math.max(...data);
zoomMinValue = actualLowestValue - ((actualHighestValue - actualLowestValue) / 2);
zoomMaxValue = actualHighestValue + ((actualHighestValue - actualLowestValue) / 2);
zoomAvgValue = (zoomMaxValue - zoomMinValue) / 2 + zoomMinValue;
// Clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Draw the signal graph with zoom
context.beginPath();
context.moveTo(50, canvas.height - (data[0] - zoomMinValue) * (canvas.height / (zoomMaxValue - zoomMinValue)));
for (let i = 1; i < data.length; i++) {
const x = i * pointWidth;
const y = canvas.height - (data[i] - zoomMinValue) * (canvas.height / (zoomMaxValue - zoomMinValue));
context.lineTo(x + 40, y);
}
context.strokeStyle = color4;
context.lineWidth = 1;
context.stroke();
// Draw horizontal lines for lowest, highest, and average values
context.strokeStyle = color2; // Set line color
context.lineWidth = 1;
// Draw the lowest value line
const lowestY = canvas.height - (zoomMinValue - zoomMinValue) * (canvas.height / (zoomMaxValue - zoomMinValue));
context.beginPath();
context.moveTo(40, lowestY - 18);
context.lineTo(canvas.width - 40, lowestY - 18);
context.stroke();
// Draw the highest value line
const highestY = canvas.height - (zoomMaxValue - zoomMinValue) * (canvas.height / (zoomMaxValue - zoomMinValue));
context.beginPath();
context.moveTo(40, highestY + 10);
context.lineTo(canvas.width - 40, highestY + 10);
context.stroke();
const avgY = canvas.height / 2;
context.beginPath();
context.moveTo(40, avgY - 7);
context.lineTo(canvas.width - 40, avgY - 7);
context.stroke();
// Label the lines with their values
context.fillStyle = color4;
context.font = '12px Titillium Web';
const offset = signalToggle.prop('checked') ? 11.75 : 0;
context.textAlign = 'right';
context.fillText(`${(zoomMinValue - offset).toFixed(1)}`, 35, lowestY - 14);
context.fillText(`${(zoomMaxValue - offset).toFixed(1)}`, 35, highestY + 14);
context.fillText(`${(zoomAvgValue - offset).toFixed(1)}`, 35, avgY - 3);
context.textAlign = 'left';
context.fillText(`${(zoomMinValue - offset).toFixed(1)}`, canvas.width - 35, lowestY - 14);
context.fillText(`${(zoomMaxValue - offset).toFixed(1)}`, canvas.width - 35, highestY + 14);
context.fillText(`${(zoomAvgValue - offset).toFixed(1)}`, canvas.width - 35, avgY - 3);
// Update the data container with the latest data
dataContainer.html(event.data + '
');
};
requestAnimationFrame(updateCanvas);
}
function compareNumbers(a, b) {
return a - b;
}
function escapeHTML(unsafeText) {
let div = document.createElement('div');
div.innerText = unsafeText;
return div.innerHTML.replace(' ', ' ');
}
function processString(string, errors) {
var output = '';
const max_alpha = 70;
const alpha_range = 50;
const max_error = 10;
errors = errors?.split(',');
for (let i = 0; i < string.length; i++) {
alpha = parseInt(errors[i]) * (alpha_range / (max_error + 1));
if (alpha) {
output += "" + escapeHTML(string[i]) + "";
} else {
output += escapeHTML(string[i]);
}
}
return output;
}
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 = $('