6

I am using express-ws https://www.npmjs.com/package/express-ws (API which helps creating server for express and websocket clients).

app.ws('/', function(ws, req) {
  console.log("New connection")
  if (content.length > 0) {
    console.log(content)
    ws.send(content)
  }
  ws.on('message', function(msg, flags) {
    console.log("Received "+ msg);
  });
  ws.on('data', function(msg, flags) {
    var data = []; // List of Buffer objects
    res.on("data", function(chunk) {
      data.push(chunk); // Append Buffer object
      console.log(data)
    })
  })
});

Now as you can see with code above, whenever a connection is created it checks length of content and sends conetent to client if more than 0.

Following router code, on web request, updates the file. Issue with this if sometime after connection creation if this file was modified, this connection doesn't know about it and hence send function is not called. I also tried fs.watch but i am not able to make it to work.

router.post('/run_restart', function(req, res, next) {
  text = '{"to_do": "run_test", "devices":"all", "argv": { "test": "' + req.body.cmd + '", "cycles": "' + req.body.cycles + '", "awake_for": "' + req.body.wt + '" }}'
  path = process.env['HOME']+'/Desktop/automation/Stressem/StressemWeb/bin/task.txt'
  fs.writeFile(path, text)
  res.render('home.jade', { title: 'Stressem' });
});

fs.watch(file, function (event) {
  fs.stat(file, function (err, stats) {
    if(stats.size>80){
      console.log("Event: " + event);
      fs.readFile(file, 'utf8', function (err, data) {
        if (err) throw err;
        content = data.toString();
      });
    }
  });

What i would like is whenever the file is updated, ws.send can be called for one of the websocket connection.

bruceparker
  • 1,235
  • 1
  • 17
  • 33

3 Answers3

5

Since your server is the one that changes the file, there's no need to use fs.watch as you already know when a file changes. All that's left to do is iterate over a list of open connections and send them the new contents.

var connections = []; // Keeps track of all connections
app.ws('/', function(ws, req) {
   console.log("New connection")
   connections.push(ws); // Add the new connection to the list

  if (content.length > 0) {
    console.log(content)
    ws.send(content)
  }
  ws.on('message', function(msg, flags) {
    console.log("Received "+ msg);
  });
  ws.on('data', function(msg, flags) {
    var data = []; // List of Buffer objects
    res.on("data", function(chunk) {
      data.push(chunk); // Append Buffer object
      console.log(data)
    })
  })
  // TODO: Make sure you remove closed connections from `connections`
  // by listening for the ws `close` event.
});

router.post('/run_restart', function(req, res, next) {
  text = '{"to_do": "run_test", "devices":"all", "argv": { "test": "' + req.body.cmd + '", "cycles": "' + req.body.cycles + '", "awake_for": "' + req.body.wt + '" }}'
  path = process.env['HOME']+'/Desktop/automation/Stressem/StressemWeb/bin/task.txt'
  fs.writeFile(path, text)
  res.render('home.jade', { title: 'Stressem' });

  connections.forEach(function(c){
    c.send(text); // Send the new text to all open connections
  }
});

Please note: this won't work if you have multiple processes or servers, but since you're writing to the local file system instead of a database, I assume this is not a requirement.

Rudolf Meijering
  • 1,559
  • 1
  • 14
  • 20
2

This simple code work good with express. If a few delay not a problem for you, you can use this.

setInterval(milisecondsToCheck, checkFunction)

for more

http://www.w3schools.com/jsref/met_win_setinterval.asp

https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval

if you use it like this, you can finish it after your job done:

var timer = setInterval(milisecondsToCheck, checkFunction);

To clear it:

clearInterval(timer);
bmavus
  • 892
  • 1
  • 7
  • 21
  • Thank you for you rtime looking into this. But the problem remains the same. How do i call this function for a particular connection? – bruceparker Mar 23 '16 at 01:27
  • check this http://stackoverflow.com/questions/9935920/how-to-write-a-node-js-function-that-waits-for-an-event-to-fire-before-returnin – bmavus Mar 23 '16 at 09:46
2

solved this with something like this

var conn_array = [];
app.ws('/', function(ws, req) {
    conn_array.push(ws)
    console.log("New connection")

    fs.readFile(file, 'utf8', function (err, data) {
        if (err) throw err;
        content = data.toString();
        if (content.length > 0) {
            console.log(content.length)
            conn_array[0].send(content)
        }
    });


    ws.on('message', function(msg, flags) {
        console.log("Received "+ msg);
    });

    ws.on('data', function(msg, flags) {
        var data = []; // List of Buffer objects
        res.on("data", function(chunk) {
            data.push(chunk); // Append Buffer object
            console.log(data)
        })
    })
});

function readFile(){
    console.log("I am here")
    fs.readFile(file, 'utf8', function (err, data) {
        if (err) throw err;
        content = data.toString();
        if (content.length > 0 && conn_array.length>0) conn_array[0].send(content);
    })
}

var interval = setInterval(readFile, 100000);

for now i have assumed there is just one client

bruceparker
  • 1,235
  • 1
  • 17
  • 33