Last active
February 16, 2024 14:04
-
-
Save bkram/bdd3ac50cba7f5df224e7bd15e524ff6 to your computer and use it in GitHub Desktop.
fm-dx-console.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// (c) Bkram | |
// Console client for https://github.com/NoobishSVK/fm-dx-webserver | |
// No audio (yet) | |
// Import necessary libraries | |
const blessed = require('blessed'); // Library for creating terminal-based UI | |
const WebSocket = require('ws'); // WebSocket library for communication | |
const argv = require('minimist')(process.argv.slice(2)); // Library for parsing command-line arguments | |
// Check if required arguments are provided | |
if (!argv.url) { | |
console.error('Usage: node script.js --url <websocket_address>'); | |
process.exit(1); | |
} | |
// Extract websocket address from command line arguments | |
const websocketAddress = argv.url; | |
// Create a Blessed screen | |
const screen = blessed.screen({ smartCSR: true }); | |
// Create a title element | |
const title = blessed.text({ | |
top: 0, | |
left: 0, | |
width: '100%', // Set width to occupy the full width of the screen | |
content: ` fm-dx-webserver console - URL: ${websocketAddress}`, // Include the URL | |
tags: true, | |
style: { | |
fg: 'white', | |
bg: 'blue', | |
bold: true // Make the title bold | |
}, | |
}); | |
// Create a clock widget | |
const clock = blessed.text({ | |
top: 0, | |
right: 0, | |
width: '10%', // Set width to occupy 20% of the screen | |
align: 'right', | |
content: '{bold}00:00{/bold}', // Initial placeholder content | |
tags: true, | |
style: { | |
fg: 'white', | |
bg: 'blue' | |
}, | |
}); | |
// Create a box to display main content | |
const mainBox = blessed.box({ | |
top: 1, // Leave space for the title | |
left: 0, | |
width: '28%', // Occupy 80% of the screen width | |
height: '50%', // Reduce height to accommodate the additional view below | |
tags: true, | |
border: { type: 'line' }, | |
style: { fg: 'white', border: { fg: '#f0f0f0' } }, | |
}); | |
// Create a box for City, Distance, and Station | |
const cityDistanceStationBox = blessed.box({ | |
top: 1, | |
left: '26%', // Position it to the right of the main box | |
width: '40%', // Occupy 50% of the screen width | |
height: '50%', // Occupy 40% of the screen height | |
tags: true, | |
border: { type: 'line' }, | |
style: { fg: 'white', border: { fg: '#f0f0f0' } }, | |
}); | |
// Create a box to display help information | |
const helpBox = blessed.box({ | |
top: 1, // Leave space for the title | |
left: '60%', // Position it to the right of the main box | |
width: '40%', // Occupy 20% of the screen width | |
height: '50%', // Same height as the main box | |
content: '{center}{bold}Help{/bold}{/center}\n Press keys:\n \'q\' to decrease by 1000 kHz\n \'w\' to increase by 1000 kHz\n \'z\' to decrease by 10 kHz\n \'x\' to increase by 10 kHz\n \'a\' to decrease by 100 kHz\n \'s\' to increase 100 kHz\n \'e\' to quit', | |
tags: true, | |
border: { type: 'line' }, | |
style: { fg: 'white', border: { fg: '#f0f0f0' } }, | |
}); | |
// Create a box for RT0 and RT1 | |
const rtBox = blessed.box({ | |
top: '50%', // Position it below the main box | |
left: 0, | |
width: '100%', // Occupy 50% of the screen width | |
height: '25%', // Occupy 40% of the screen height | |
tags: true, | |
border: { type: 'line' }, | |
style: { fg: 'white', border: { fg: '#f0f0f0' } }, | |
}); | |
// Append title, clock, main box, help box, rt box, and cityDistanceStation box to the screen | |
screen.append(title); | |
screen.append(clock); | |
screen.append(mainBox); | |
screen.append(cityDistanceStationBox); | |
screen.append(helpBox); | |
screen.append(rtBox); | |
// Function to update the main box content | |
function updateMainBoxContent(content) { | |
mainBox.setContent(content); | |
screen.render(); | |
} | |
// Function to update the RT box content | |
function updateRTBoxContent(rt0, rt1) { | |
rtBox.setContent(`{center}{bold}Radiotext{/bold}{/center}\n{center}${rt0.trim()}{/center}\n{center}${rt1.trim()}{/center}`); | |
screen.render(); | |
} | |
// Function to update the City, Distance, and Station box content | |
function stationData(city, distance, station, power, country, polarization, azimuth) { | |
cityDistanceStationBox.setContent(`{center}{bold}Station Data{/bold}{/center}\n Station: ${station}\n City: ${city}, ${country}\n Distance: ${distance} km\n Power: ${power} kW [${polarization}]\n Country: ${country}\n Azimuth: ${azimuth}`); | |
screen.render(); | |
} | |
// Update clock function | |
function updateClock() { | |
const now = new Date(); | |
const hours = ('0' + now.getHours()).slice(-2); // Get hours in 2-digit format | |
const minutes = ('0' + now.getMinutes()).slice(-2); // Get minutes in 2-digit format | |
const timeString = `${hours}:${minutes}`; | |
clock.setContent(`{right}{bold}${timeString}{/bold}{/right}`); | |
screen.render(); | |
} | |
// Update clock every second | |
setInterval(updateClock, 1000); | |
// Initialize JSON data variable | |
let jsonData = null; | |
// WebSocket setup | |
const ws = new WebSocket(websocketAddress); | |
// WebSocket event handlers | |
ws.on('open', function () { | |
updateMainBoxContent('WebSocket connection established'); | |
}); | |
ws.on('message', function (data) { | |
try { | |
jsonData = JSON.parse(data); | |
const content = `{center}{bold}Tuner{/bold}{/center}\n PS: ${jsonData.ps}\n PI: ${jsonData.pi}\n Frequency: ${jsonData.freq}\n Signal: ${jsonData.signal}\n Stereo: ${jsonData.st}\n `; | |
updateMainBoxContent(content); | |
if (jsonData && jsonData.txInfo) { | |
stationData(jsonData.txInfo.city, jsonData.txInfo.distance, jsonData.txInfo.station, jsonData.txInfo.erp, jsonData.txInfo.itu, jsonData.txInfo.pol, jsonData.txInfo.azimuth); | |
} | |
if (jsonData && jsonData.rt0 !== undefined && jsonData.rt1 !== undefined) { | |
updateRTBoxContent(jsonData.rt0, jsonData.rt1); | |
} | |
} catch (error) { | |
console.error('Error parsing JSON:', error); | |
} | |
}); | |
ws.on('close', function () { | |
updateMainBoxContent('WebSocket connection closed'); | |
}); | |
// Listen for key events | |
screen.on('keypress', function (ch, key) { | |
if (key.full === 's') { // Decrease frequency by 100 kHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) + 100; | |
ws.send(`T${newFreq}`); | |
} | |
} else if (key.full === 'a') { // Increase frequency by 100 kHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) - 100; | |
ws.send(`T${newFreq}`); | |
} | |
} else if (key.full === 'q') { // Decrease frequency by 1 MHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) - 1000; | |
ws.send(`T${newFreq}`); | |
} | |
} else if (key.full === 'w') { // Increase frequency by 1 MHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) + 1000; | |
ws.send(`T${newFreq}`); | |
} | |
} else if (key.full === 'z') { // Decrease frequency by 0.01 MHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) - 10; | |
ws.send(`T${newFreq}`); | |
} | |
} else if (key.full === 'x') { // Increase frequency by 0.01 MHz | |
if (jsonData && jsonData.freq) { | |
const newFreq = (jsonData.freq * 1000) + 10; | |
ws.send(`T${newFreq}`); | |
} | |
} | |
}); | |
// Quit on Escape, q, or Control-C | |
screen.key(['escape', 'e', 'C-c'], function () { | |
process.exit(0); | |
}); | |
// Update clock initially | |
updateClock(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment