Socket.io emit button press to all clients

I am having some trouble sending a button state to all clients connected to my server. I am trying to turn on a light from a raspberry pi hosted server using express and socket.io.

I first click the button from the client and it will send the state of the button to my server which then emits it to all clients which clicks the button on all clients page but then button then gets stuck in an endless loop and continues to click.

Is the process that I am doing correct? I can find lots of examples of emitting to all clients but I am unable to find any that emit the state of a button. I also tried to emit.broadcast but the two clients took turns sending the button state endlessly.

Does anyone have any suggestions for fixing this problem? Thanks!

Server Side Code:

var express = require('express');  
var app = express();  
var server = require('http').createServer(app);  
var io = require('socket.io')(server);

var onoff = require('onoff'); 
var Gpio = onoff.Gpio;
var light = new Gpio(13, 'out');


app.use(express.static(__dirname + '/'));  
app.get('/', function(req, res,next) {  
res.sendFile(__dirname + '/brew.html');
 });

console.log('Starting Server...');

  var io = require('socket.io').listen(server);
  io.sockets.on('connection', function (client) {

  client.on('lightOn',function(on){
    light.writeSync(1);
    io.emit('lightOn');
  });
  client.on('lightOff',function(off){
    light.writeSync(0);
    io.emit('lightOff');
   });
  });

 server.listen(3000);

 function lightOn(){
 light.writeSync(1);
 }
   function lightOff(){
   light.writeSync(0);
  }

Client Code:

  <h3 id="h3Brew">Light</h3>
  <input type="checkbox" data-toggle="toggle" data-on="Off" data-off="On" id="toggle">

  <script>
  var socket = io.connect();
  $(function() {
  $('#toggle').bootstrapToggle({
      on: 'ON',
      off: 'OFF'
    });
  })
        $("#toggle").change(function(){
          if($("#toggle").prop("checked") == true){
           socket.emit('lightOn', 'on\n');
          }else{
           socket.emit('lightOff', 'off\n');}
         });

        socket.on('lightOn', function() {
          $('#toggle').bootstrapToggle('on');
        });
         socket.on('lightOff', function() {
          $('#toggle').bootstrapToggle('off');
        });

    </script>

Answers 1

  • Use a global variable to differentiate between a change event triggered by the socked and one triggered by the user

    You can try something like this

    var websocket = false;
    $("#toggle").change(function(){
          if(!websocket) {
              if($("#toggle").prop("checked") == true){
               socket.emit('lightOn', 'on\n');
              }else{
               socket.emit('lightOff', 'off\n');}
          } else {websocket = false;}
             });
    
            socket.on('lightOn', function() {
              websocket = true;
              $('#toggle').bootstrapToggle('on');
            });
             socket.on('lightOff', function() {
              websocket = true;
              $('#toggle').bootstrapToggle('off');
    
            });
    

Related Articles