@@ -8,6 +8,7 @@ const path = require("path")
88const cors = require ( 'cors' ) ;
99const morgan = require ( 'morgan' ) ;
1010const fetch = require ( 'node-fetch' ) ; // Fetch for API requests
11+ const WebSocket = require ( 'ws' ) ; // WebSocket server
1112var dxcc ;
1213
1314//Load config from file or from environment variables
@@ -40,6 +41,9 @@ app.use(express.json());
4041app . use ( morgan ( ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" :response-time ms' ) ) ;
4142app . use ( cors ( { origin : '*' } ) ) ;
4243
44+ // Serve static files (for demo page)
45+ app . use ( config . baseUrl + '/demo' , express . static ( path . join ( __dirname , 'public' ) ) ) ;
46+
4347// DXCluster connection and spot cache
4448let spots = [ ] ;
4549
@@ -48,6 +52,32 @@ const bandIndex = new Map(); // Map<band, Set<spot>>
4852const frequencyIndex = new Map ( ) ; // Map<frequency, spot>
4953const sourceIndex = new Map ( ) ; // Map<source, Set<spot>>
5054
55+ // WebSocket clients
56+ const wsClients = new Set ( ) ;
57+
58+ /**
59+ * Broadcasts a new spot to all connected WebSocket clients
60+ */
61+ function broadcastSpot ( spot ) {
62+ if ( wsClients . size === 0 ) return ;
63+
64+ const message = JSON . stringify ( {
65+ type : 'spot' ,
66+ data : spot
67+ } ) ;
68+
69+ wsClients . forEach ( ( client ) => {
70+ if ( client . readyState === WebSocket . OPEN ) {
71+ try {
72+ client . send ( message ) ;
73+ } catch ( error ) {
74+ console . error ( 'Error sending to WebSocket client:' , error ) ;
75+ wsClients . delete ( client ) ;
76+ }
77+ }
78+ } ) ;
79+ }
80+
5181
5282// -----------------------------------
5383// Utility Functions
@@ -206,9 +236,29 @@ app.get(config.baseUrl + '/stats', (req, res) => {
206236 */
207237async function main ( ) {
208238 try {
209- app . listen ( config . webport , '0.0.0.0' , ( ) => {
239+ const server = app . listen ( config . webport , '0.0.0.0' , ( ) => {
210240 console . log ( `Listener started on Port ${ config . webport } ` ) ;
211241 } ) ;
242+
243+ // Create WebSocket server
244+ const wss = new WebSocket . Server ( { server } ) ;
245+
246+ wss . on ( 'connection' , ( ws ) => {
247+ console . log ( 'New WebSocket client connected' ) ;
248+ wsClients . add ( ws ) ;
249+
250+ ws . on ( 'close' , ( ) => {
251+ console . log ( 'WebSocket client disconnected' ) ;
252+ wsClients . delete ( ws ) ;
253+ } ) ;
254+
255+ ws . on ( 'error' , ( error ) => {
256+ console . error ( 'WebSocket error:' , error ) ;
257+ wsClients . delete ( ws ) ;
258+ } ) ;
259+ } ) ;
260+
261+ console . log ( `WebSocket server started on Port ${ config . webport } ` ) ;
212262 reconnect ( ) ; // Start the connection to DXCluster
213263 } catch ( e ) {
214264 console . error ( "Error starting server:" , e ) ;
@@ -279,6 +329,9 @@ async function handlespot(spot, spot_source = "cluster"){
279329 // Update indexes
280330 updateIndexes ( dxSpot ) ;
281331
332+ // Broadcast to WebSocket clients
333+ broadcastSpot ( dxSpot ) ;
334+
282335 //empty out spots if maximum retainment is reached
283336 if ( spots . length > config . maxcache ) {
284337 const removed = spots . shift ( ) ;
0 commit comments