avr-yamaha.js
function() {
      if (node.debug) {
        node.log('STARTING event listener');
      }

      var net = require('net');
      var dgram = require('dgram');
      node.inputSocket = dgram.createSocket({type:'udp4', reuseAddr: true});

      node.inputSocket.on('notify', function (event) {
        if (node.debug) {
          node.log('Got a notification.', event)
        }
      });

      node.inputSocket.on('message', function (msg, rinfo) {
        //node.log("[" + rinfo.address + "] --> " + msg.toString());

        if (rinfo.address == node.address) {
          if (node.debug) {
            node.log("UPnP Event from [" + rinfo.address + "] --> " );//+ msg.toString());
          }

          // Split to header and body
          msg = msg.toString().split('\r\n\r\n');
          var header = msg[0];
          var body = msg[1];

          // Ignore UPNP search requests
          var method = header.split('\r\n').shift().split(' ').shift().trim();
          if (method == 'M-SEARCH'){
            return;
          }

          // Parse rest of header
          var arr = header.match(/[^\r\n]+/g);
          var headerInfo = {};
          for (var i = 1; i < arr.length; ++i){
            var tem = arr[i].split(/:(.+)?/);
            if (typeof(tem[1]) == 'string'){ tem[1] = tem[1].trim(); }
            headerInfo[tem[0].toLowerCase()] = tem[1];
          };
          //node.log("METHOD: " + method);
          //node.log("BODY: " + body);
          //node.log("NTS: " + headerInfo['nts']);

          // NOTIFY messages tell us about the properties that changed
          if (method == 'NOTIFY' && headerInfo['nts'] == 'yamaha:propchange') {

            var parseString = require('xml2js').parseString;
            parseString(body, function (err, result) {
              if (err) {
                node.error('Failed to parse the event with error: ' + err);
                return;
              }

              // Check the received object
              var zoneName = undefined;
              if (result.hasOwnProperty('YAMAHA_AV')) {
                if (result.YAMAHA_AV.hasOwnProperty('Main_Zone')) {
                  zoneName = 'Main_Zone';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_2')) {
                  zoneName = 'Zone_2';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_3')) {
                  zoneName = 'Zone_3';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_4')) {
                  zoneName = 'Zone_4';
                }
              }
              if (zoneName === undefined
                || result.YAMAHA_AV[zoneName] === undefined
                || result.YAMAHA_AV[zoneName][0] === undefined) {
                if (node.debug) {
                  node.warn('Unknown event message format: ' + JSON.stringify(result));
                }
                return;
              }

              for (var i in result.YAMAHA_AV[zoneName][0].Property) {
                var prop = result.YAMAHA_AV[zoneName][0].Property[i];
                if (node.debug) {
                  node.log('Property-Change: ' + prop);
                }

                // Event Notification only notifies that there is a change in each item.
                // It is necessary to issue the GET command to obtain the content of the item with the change.
                if (prop == 'Power') {

                  // Get current power state and publish to all subscriber.
                  node.sendGetCommand(zoneName + '.Power_Control.Power').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Power_Control.Power', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Input') {

                  // Get current input selection and publish to all subscriber.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Input.Input_Sel', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Volume') {

                  // We don't know from the event itself if volume changed or mute/unmute was pressed.
                  // Therefore we read both states.
                  node.sendGetCommand(zoneName + '.Volume.Lvl').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Volume.Lvl', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });
                  node.sendGetCommand(zoneName + '.Volume.Mute').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Volume.Mute', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Play_Info') {

                  // When getting the Play_Info event we need to check the current input mode and then read
                  // the corresponding item that holds info about current mode.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {

                    var validInputs = {
                      'TUNER': 'Tuner', 'Napster': 'Napster', 'Spotify': 'Spotify', 'JUKE': 'JUKE', 'SERVER': 'SERVER',
                      'NET RADIO': 'NET_RADIO', 'USB': 'USB', 'iPod_USB': 'iPod_USB', 'AirPlay': 'AirPlay'
                    };

                    if (validInputs.hasOwnProperty(value)) {
                      node.sendGetCommand(validInputs[value] + '.Play_Info').then(function(value2) {
                        for (var s in node.subscriptions) {
                          node.subscriptions[s].handler(value + '.Play_Info', value2);
                        }
                      }).catch(function(error) {
                        node.error('Received event Play_Info but failed to read play info of current input selection: ' + error);
                      });
                    } else {
                      if (node.debug) {
                        node.log('Received event Play_Info but do not know or support current input selection ' + value);
                      }
                    }
                  }).catch(function(error) {
                    node.error('Received event Play_Info but failed to read current input selection: ' + error);
                  });

                } else if (prop == 'List_Info') {

                  // When getting the List_info event we need to check the current input mode and then read
                  // the corresponding item that holds info about current mode.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {

                    var validInputs = {
                      'Napster': 'Napster', 'JUKE': 'JUKE', 'SERVER': 'SERVER',
                      'NET RADIO': 'NET_RADIO', 'USB': 'USB', 'iPod_USB': 'iPod_USB'
                    };

                    if (validInputs.hasOwnProperty(value)) {
                      node.sendGetCommand(validInputs[value] + '.List_Info').then(function(value2) {
                        for (var s in node.subscriptions) {
                          node.subscriptions[s].handler(value + '.List_Info', value2);
                        }
                      }).catch(function(error) {
                        node.error('Received event List_Info but failed to read play info of current input selection: ' + error);
                      });
                    } else {
                      if (node.debug) {
                        node.log('Received event List_Info but do not know or support current input selection ' + value);
                      }
                    }
                  }).catch(function(error) {
                    node.error('Received event List_Info but failed to read current input selection: ' + error);
                  });

                } else {

                  // The event is not known. Maybe the AVR is too new.
                  if (node.debug) {
                    node.log('Received unsupported Property-Change via multicast: ' + prop);
                  }
                  return;

                }
              }
            });
          }
        }
      });

      node.inputSocket.on('listening', function () {
        try {
          var address = node.inputSocket.address();
          node.log('UDP client listening on ' + address.address + ":" + address.port);
          node.inputSocket.setBroadcast(true)
          node.inputSocket.setMulticastTTL(5);
          node.inputSocket.addMembership('239.255.255.250');
          //node.inputSocket.addMembership('239.255.255.250', '192.168.0.101');
          //node.inputSocket.addMembership('239.255.255.250', '127.0.0.1');

          /*
          var message = new Buffer(
            "M-SEARCH * HTTP/1.1\r\n" +
            "HOST: 239.255.255.250:1900\r\n" +
            "MAN: \"ssdp:discover\"\r\n" +
            "ST: ssdp:all\r\n" + // Essential, used by the client to specify what they want to discover, eg 'ST:ge:fridge'
            "MX: 3\r\n" + // 1 second to respond (but they all respond immediately?)
            "\r\n");
          */

            //node.inputSocket.send(message, 0, message.length, 1900, "239.255.255.250");
          } catch (err) {
            node.warn('Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err);
          }
        });

      try {
        node.inputSocket.bind(1900);
      }
      catch (err) {
        node.warn('Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err);
      }
    }
function() {
      if (node.debug) {
        node.log('STARTING event listener');
      }

      var net = require('net');
      var dgram = require('dgram');
      node.inputSocket = dgram.createSocket({type:'udp4', reuseAddr: true});

      node.inputSocket.on('notify', function (event) {
        if (node.debug) {
          node.log('Got a notification.', event)
        }
      });

      node.inputSocket.on('message', function (msg, rinfo) {
        //node.log("[" + rinfo.address + "] --> " + msg.toString());

        if (rinfo.address == node.address) {
          if (node.debug) {
            node.log("UPnP Event from [" + rinfo.address + "] --> " );//+ msg.toString());
          }

          // Split to header and body
          msg = msg.toString().split('\r\n\r\n');
          var header = msg[0];
          var body = msg[1];

          // Ignore UPNP search requests
          var method = header.split('\r\n').shift().split(' ').shift().trim();
          if (method == 'M-SEARCH'){
            return;
          }

          // Parse rest of header
          var arr = header.match(/[^\r\n]+/g);
          var headerInfo = {};
          for (var i = 1; i < arr.length; ++i){
            var tem = arr[i].split(/:(.+)?/);
            if (typeof(tem[1]) == 'string'){ tem[1] = tem[1].trim(); }
            headerInfo[tem[0].toLowerCase()] = tem[1];
          };
          //node.log("METHOD: " + method);
          //node.log("BODY: " + body);
          //node.log("NTS: " + headerInfo['nts']);

          // NOTIFY messages tell us about the properties that changed
          if (method == 'NOTIFY' && headerInfo['nts'] == 'yamaha:propchange') {

            var parseString = require('xml2js').parseString;
            parseString(body, function (err, result) {
              if (err) {
                node.error('Failed to parse the event with error: ' + err);
                return;
              }

              // Check the received object
              var zoneName = undefined;
              if (result.hasOwnProperty('YAMAHA_AV')) {
                if (result.YAMAHA_AV.hasOwnProperty('Main_Zone')) {
                  zoneName = 'Main_Zone';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_2')) {
                  zoneName = 'Zone_2';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_3')) {
                  zoneName = 'Zone_3';
                } else if (result.YAMAHA_AV.hasOwnProperty('Zone_4')) {
                  zoneName = 'Zone_4';
                }
              }
              if (zoneName === undefined
                || result.YAMAHA_AV[zoneName] === undefined
                || result.YAMAHA_AV[zoneName][0] === undefined) {
                if (node.debug) {
                  node.warn('Unknown event message format: ' + JSON.stringify(result));
                }
                return;
              }

              for (var i in result.YAMAHA_AV[zoneName][0].Property) {
                var prop = result.YAMAHA_AV[zoneName][0].Property[i];
                if (node.debug) {
                  node.log('Property-Change: ' + prop);
                }

                // Event Notification only notifies that there is a change in each item.
                // It is necessary to issue the GET command to obtain the content of the item with the change.
                if (prop == 'Power') {

                  // Get current power state and publish to all subscriber.
                  node.sendGetCommand(zoneName + '.Power_Control.Power').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Power_Control.Power', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Input') {

                  // Get current input selection and publish to all subscriber.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Input.Input_Sel', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Volume') {

                  // We don't know from the event itself if volume changed or mute/unmute was pressed.
                  // Therefore we read both states.
                  node.sendGetCommand(zoneName + '.Volume.Lvl').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Volume.Lvl', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });
                  node.sendGetCommand(zoneName + '.Volume.Mute').then(function(value) {
                    for (var s in node.subscriptions) {
                      node.subscriptions[s].handler(zoneName + '.Volume.Mute', value);
                    }
                  }).catch(function(error) {
                    node.error('Failed to request data from AVR with error: ' + error);
                  });

                } else if (prop == 'Play_Info') {

                  // When getting the Play_Info event we need to check the current input mode and then read
                  // the corresponding item that holds info about current mode.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {

                    var validInputs = {
                      'TUNER': 'Tuner', 'Napster': 'Napster', 'Spotify': 'Spotify', 'JUKE': 'JUKE', 'SERVER': 'SERVER',
                      'NET RADIO': 'NET_RADIO', 'USB': 'USB', 'iPod_USB': 'iPod_USB', 'AirPlay': 'AirPlay'
                    };

                    if (validInputs.hasOwnProperty(value)) {
                      node.sendGetCommand(validInputs[value] + '.Play_Info').then(function(value2) {
                        for (var s in node.subscriptions) {
                          node.subscriptions[s].handler(value + '.Play_Info', value2);
                        }
                      }).catch(function(error) {
                        node.error('Received event Play_Info but failed to read play info of current input selection: ' + error);
                      });
                    } else {
                      if (node.debug) {
                        node.log('Received event Play_Info but do not know or support current input selection ' + value);
                      }
                    }
                  }).catch(function(error) {
                    node.error('Received event Play_Info but failed to read current input selection: ' + error);
                  });

                } else if (prop == 'List_Info') {

                  // When getting the List_info event we need to check the current input mode and then read
                  // the corresponding item that holds info about current mode.
                  node.sendGetCommand(zoneName + '.Input.Input_Sel').then(function(value) {

                    var validInputs = {
                      'Napster': 'Napster', 'JUKE': 'JUKE', 'SERVER': 'SERVER',
                      'NET RADIO': 'NET_RADIO', 'USB': 'USB', 'iPod_USB': 'iPod_USB'
                    };

                    if (validInputs.hasOwnProperty(value)) {
                      node.sendGetCommand(validInputs[value] + '.List_Info').then(function(value2) {
                        for (var s in node.subscriptions) {
                          node.subscriptions[s].handler(value + '.List_Info', value2);
                        }
                      }).catch(function(error) {
                        node.error('Received event List_Info but failed to read play info of current input selection: ' + error);
                      });
                    } else {
                      if (node.debug) {
                        node.log('Received event List_Info but do not know or support current input selection ' + value);
                      }
                    }
                  }).catch(function(error) {
                    node.error('Received event List_Info but failed to read current input selection: ' + error);
                  });

                } else {

                  // The event is not known. Maybe the AVR is too new.
                  if (node.debug) {
                    node.log('Received unsupported Property-Change via multicast: ' + prop);
                  }
                  return;

                }
              }
            });
          }
        }
      });

      node.inputSocket.on('listening', function () {
        try {
          var address = node.inputSocket.address();
          node.log('UDP client listening on ' + address.address + ":" + address.port);
          node.inputSocket.setBroadcast(true)
          node.inputSocket.setMulticastTTL(5);
          node.inputSocket.addMembership('239.255.255.250');
          //node.inputSocket.addMembership('239.255.255.250', '192.168.0.101');
          //node.inputSocket.addMembership('239.255.255.250', '127.0.0.1');

          /*
          var message = new Buffer(
            "M-SEARCH * HTTP/1.1\r\n" +
            "HOST: 239.255.255.250:1900\r\n" +
            "MAN: \"ssdp:discover\"\r\n" +
            "ST: ssdp:all\r\n" + // Essential, used by the client to specify what they want to discover, eg 'ST:ge:fridge'
            "MX: 3\r\n" + // 1 second to respond (but they all respond immediately?)
            "\r\n");
          */

            //node.inputSocket.send(message, 0, message.length, 1900, "239.255.255.250");
          } catch (err) {
            node.warn('Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err);
          }
        });

      try {
        node.inputSocket.bind(1900);
      }
      catch (err) {
        node.warn('Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err);
      }
    }
function ( ) { if ( node . debug ) { node . log ( 'STARTING event listener' ) ; } var net = require ( 'net' ) ; var dgram = require ( 'dgram' ) ; node . inputSocket = dgram . createSocket ( { type : 'udp4' , reuseAddr : true } ) ; node . inputSocket . on ( 'notify' , function ( event ) { if ( node . debug ) { node . log ( 'Got a notification.' , event ) } } ) ; node . inputSocket . on ( 'message' , function ( msg , rinfo ) { //node.log("[" + rinfo.address + "] --> " + msg.toString()); if ( rinfo . address == node . address ) { if ( node . debug ) { node . log ( "UPnP Event from [" + rinfo . address + "] --> " ) ; //+ msg.toString()); } // Split to header and body msg = msg . toString ( ) . split ( '\r\n\r\n' ) ; var header = msg [ 0 ] ; var body = msg [ 1 ] ; // Ignore UPNP search requests var method = header . split ( '\r\n' ) . shift ( ) . split ( ' ' ) . shift ( ) . trim ( ) ; if ( method == 'M-SEARCH' ) { return ; } // Parse rest of header var arr = header . match ( / [^\r\n]+ / g ) ; var headerInfo = { } ; for ( var i = 1 ; i < arr . length ; ++ i ) { var tem = arr [ i ] . split ( / :(.+)? / ) ; if ( typeof ( tem [ 1 ] ) == 'string' ) { tem [ 1 ] = tem [ 1 ] . trim ( ) ; } headerInfo [ tem [ 0 ] . toLowerCase ( ) ] = tem [ 1 ] ; } ; //node.log("METHOD: " + method); //node.log("BODY: " + body); //node.log("NTS: " + headerInfo['nts']); // NOTIFY messages tell us about the properties that changed if ( method == 'NOTIFY' && headerInfo [ 'nts' ] == 'yamaha:propchange' ) { var parseString = require ( 'xml2js' ) . parseString ; parseString ( body , function ( err , result ) { if ( err ) { node . error ( 'Failed to parse the event with error: ' + err ) ; return ; } // Check the received object var zoneName = undefined ; if ( result . hasOwnProperty ( 'YAMAHA_AV' ) ) { if ( result . YAMAHA_AV . hasOwnProperty ( 'Main_Zone' ) ) { zoneName = 'Main_Zone' ; } else if ( result . YAMAHA_AV . hasOwnProperty ( 'Zone_2' ) ) { zoneName = 'Zone_2' ; } else if ( result . YAMAHA_AV . hasOwnProperty ( 'Zone_3' ) ) { zoneName = 'Zone_3' ; } else if ( result . YAMAHA_AV . hasOwnProperty ( 'Zone_4' ) ) { zoneName = 'Zone_4' ; } } if ( zoneName === undefined || result . YAMAHA_AV [ zoneName ] === undefined || result . YAMAHA_AV [ zoneName ] [ 0 ] === undefined ) { if ( node . debug ) { node . warn ( 'Unknown event message format: ' + JSON . stringify ( result ) ) ; } return ; } for ( var i in result . YAMAHA_AV [ zoneName ] [ 0 ] . Property ) { var prop = result . YAMAHA_AV [ zoneName ] [ 0 ] . Property [ i ] ; if ( node . debug ) { node . log ( 'Property-Change: ' + prop ) ; } // Event Notification only notifies that there is a change in each item. // It is necessary to issue the GET command to obtain the content of the item with the change. if ( prop == 'Power' ) { // Get current power state and publish to all subscriber. node . sendGetCommand ( zoneName + '.Power_Control.Power' ) . then ( function ( value ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( zoneName + '.Power_Control.Power' , value ) ; } } ) . catch ( function ( error ) { node . error ( 'Failed to request data from AVR with error: ' + error ) ; } ) ; } else if ( prop == 'Input' ) { // Get current input selection and publish to all subscriber. node . sendGetCommand ( zoneName + '.Input.Input_Sel' ) . then ( function ( value ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( zoneName + '.Input.Input_Sel' , value ) ; } } ) . catch ( function ( error ) { node . error ( 'Failed to request data from AVR with error: ' + error ) ; } ) ; } else if ( prop == 'Volume' ) { // We don't know from the event itself if volume changed or mute/unmute was pressed. // Therefore we read both states. node . sendGetCommand ( zoneName + '.Volume.Lvl' ) . then ( function ( value ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( zoneName + '.Volume.Lvl' , value ) ; } } ) . catch ( function ( error ) { node . error ( 'Failed to request data from AVR with error: ' + error ) ; } ) ; node . sendGetCommand ( zoneName + '.Volume.Mute' ) . then ( function ( value ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( zoneName + '.Volume.Mute' , value ) ; } } ) . catch ( function ( error ) { node . error ( 'Failed to request data from AVR with error: ' + error ) ; } ) ; } else if ( prop == 'Play_Info' ) { // When getting the Play_Info event we need to check the current input mode and then read // the corresponding item that holds info about current mode. node . sendGetCommand ( zoneName + '.Input.Input_Sel' ) . then ( function ( value ) { var validInputs = { 'TUNER' : 'Tuner' , 'Napster' : 'Napster' , 'Spotify' : 'Spotify' , 'JUKE' : 'JUKE' , 'SERVER' : 'SERVER' , 'NET RADIO' : 'NET_RADIO' , 'USB' : 'USB' , 'iPod_USB' : 'iPod_USB' , 'AirPlay' : 'AirPlay' } ; if ( validInputs . hasOwnProperty ( value ) ) { node . sendGetCommand ( validInputs [ value ] + '.Play_Info' ) . then ( function ( value2 ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( value + '.Play_Info' , value2 ) ; } } ) . catch ( function ( error ) { node . error ( 'Received event Play_Info but failed to read play info of current input selection: ' + error ) ; } ) ; } else { if ( node . debug ) { node . log ( 'Received event Play_Info but do not know or support current input selection ' + value ) ; } } } ) . catch ( function ( error ) { node . error ( 'Received event Play_Info but failed to read current input selection: ' + error ) ; } ) ; } else if ( prop == 'List_Info' ) { // When getting the List_info event we need to check the current input mode and then read // the corresponding item that holds info about current mode. node . sendGetCommand ( zoneName + '.Input.Input_Sel' ) . then ( function ( value ) { var validInputs = { 'Napster' : 'Napster' , 'JUKE' : 'JUKE' , 'SERVER' : 'SERVER' , 'NET RADIO' : 'NET_RADIO' , 'USB' : 'USB' , 'iPod_USB' : 'iPod_USB' } ; if ( validInputs . hasOwnProperty ( value ) ) { node . sendGetCommand ( validInputs [ value ] + '.List_Info' ) . then ( function ( value2 ) { for ( var s in node . subscriptions ) { node . subscriptions [ s ] . handler ( value + '.List_Info' , value2 ) ; } } ) . catch ( function ( error ) { node . error ( 'Received event List_Info but failed to read play info of current input selection: ' + error ) ; } ) ; } else { if ( node . debug ) { node . log ( 'Received event List_Info but do not know or support current input selection ' + value ) ; } } } ) . catch ( function ( error ) { node . error ( 'Received event List_Info but failed to read current input selection: ' + error ) ; } ) ; } else { // The event is not known. Maybe the AVR is too new. if ( node . debug ) { node . log ( 'Received unsupported Property-Change via multicast: ' + prop ) ; } return ; } } } ) ; } } } ) ; node . inputSocket . on ( 'listening' , function ( ) { try { var address = node . inputSocket . address ( ) ; node . log ( 'UDP client listening on ' + address . address + ":" + address . port ) ; node . inputSocket . setBroadcast ( true ) node . inputSocket . setMulticastTTL ( 5 ) ; node . inputSocket . addMembership ( '239.255.255.250' ) ; //node.inputSocket.addMembership('239.255.255.250', '192.168.0.101'); //node.inputSocket.addMembership('239.255.255.250', '127.0.0.1'); /*
          var message = new Buffer(
            "M-SEARCH * HTTP/1.1\r\n" +
            "HOST: 239.255.255.250:1900\r\n" +
            "MAN: \"ssdp:discover\"\r\n" +
            "ST: ssdp:all\r\n" + // Essential, used by the client to specify what they want to discover, eg 'ST:ge:fridge'
            "MX: 3\r\n" + // 1 second to respond (but they all respond immediately?)
            "\r\n");
          */ //node.inputSocket.send(message, 0, message.length, 1900, "239.255.255.250"); } catch ( err ) { node . warn ( 'Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err ) ; } } ) ; try { node . inputSocket . bind ( 1900 ) ; } catch ( err ) { node . warn ( 'Cannot bind address for UPNP event listener. Port probably already in use. Error: ' + err ) ; } }
Internal sub routines
Internal sub routines