{"id":17962293,"url":"https://github.com/richtr/plug.play.js","last_synced_at":"2025-07-11T09:40:54.482Z","repository":{"id":5105659,"uuid":"6269457","full_name":"richtr/plug.play.js","owner":"richtr","description":"A Network Service Messaging framework for use on top of the W3C Network Service Discovery specification","archived":false,"fork":false,"pushed_at":"2012-12-06T15:37:35.000Z","size":204,"stargazers_count":39,"open_issues_count":1,"forks_count":12,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-05T02:22:30.715Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://richtr.github.com/plug.play.js","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"dcarrith/jquery.mobile.lazyloader","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/richtr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-10-17T22:03:14.000Z","updated_at":"2024-10-25T10:50:19.000Z","dependencies_parsed_at":"2022-09-04T23:01:53.806Z","dependency_job_id":null,"html_url":"https://github.com/richtr/plug.play.js","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/richtr/plug.play.js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richtr%2Fplug.play.js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richtr%2Fplug.play.js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richtr%2Fplug.play.js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richtr%2Fplug.play.js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richtr","download_url":"https://codeload.github.com/richtr/plug.play.js/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richtr%2Fplug.play.js/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264778040,"owners_count":23662559,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T11:18:30.720Z","updated_at":"2025-07-11T09:40:54.475Z","avatar_url":"https://github.com/richtr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Plug.Play.js\n====================\n\nA JavaScript API for communicating with Universal Plug and Play (UPnP) Services obtained via the [W3C Network Service Discovery draft specification (4th October 2012 version)](http://www.w3.org/TR/2012/WD-discovery-api-20121004/).\n\n### Setup\n\nThis API requires a web browser that supports [\u003ccode\u003enavigator.getNetworkServices\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#dom-navigator-getnetworkservices).\n\nOpera [released a Labs build](http://dev.opera.com/articles/view/network-service-discovery-api-support-in-opera/) that provides support for this API. You can read more and download the browser builds at the [Dev.Opera blog](http://dev.opera.com/articles/view/network-service-discovery-api-support-in-opera/).\n\n#### Download this library\n\nYou can download a [ZIP](https://github.com/richtr/plug.play.js/zipball/master) or [TAR.GZ](https://github.com/richtr/plug.play.js/tarball/master) file containing all the Plug.Play library code or you can clone this repo via Git as follows:\n\n    git clone git://github.com/richtr/plug.play.js.git\n\nTo get started, a UPnP service demo ([example.html](https://github.com/richtr/plug.play.js/blob/master/example.html)) is available and a [test suite](https://github.com/richtr/plug.play.js/blob/master/test) is also included for checking the validity of the API.\n\n### Work flow\n\nPlug.Play is an API to make working with UPnP Services simple and easy.\n\nThe basic work flow for using this API is as follows:\n\n1. Obtain one or more [\u003ccode\u003eNetworkService\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservice) objects via [\u003ccode\u003enavigator.getNetworkServices\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#dom-navigator-getnetworkservices).\n2. Create a new \u003ccode\u003ePlug.UPnP\u003c/code\u003e object for each [\u003ccode\u003eNetworkService\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservice) object returned.\n3. Invoke UPnP Service Actions via the \u003ccode\u003ePlug.UPnP\u003c/code\u003e object's \u003ccode\u003e.action()\u003c/code\u003e API method.\n\nEach step above is explained in more detail below.\n\n#### Step 1: Obtain \u003ccode\u003eNetworkService\u003c/code\u003e objects\n\nIf you are running this API in a supported browser, as discussed in the [Setup](#setup) section above, you will be able to obtain a set of [\u003ccode\u003eNetworkService\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservice) objects as follows:\n\n    if(navigator.getNetworkServices) {\n      navigator.getNetworkServices(\n        'upnp:urn:schemas-upnp-org:service:RenderingControl:1',\n        successCallback\n      );\n    }\n\nThe \u003ccode\u003esuccessCallback\u003c/code\u003e function takes one argument, a [\u003ccode\u003eNetworkServices\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservices) object that acts like an array of [\u003ccode\u003eNetworkService\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservice) objects. When services are found in the current network that match the requested service type(s) the web browser will trigger execution of this function.\n\n    function successCallback( servicesManager ) {\n      // Dump services to console\n      for( var i = 0; i \u003c servicesManager.length; i++ ) {\n        console.log( \"Service w/ type [\" +\n                        servicesManager[i].type  + \"] available\" );\n      }\n    }\n\n#### Step 2: Create a new \u003ccode\u003ePlug.UPnP\u003c/code\u003e object\n\nOnce we have a \u003ccode\u003esuccessCallback\u003c/code\u003e function defined, we can create new \u003ccode\u003ePlug.UPnP\u003c/code\u003e objects.\n\nTo create a new \u003ccode\u003ePlug.UPnP\u003c/code\u003e object we to need pass in a single (UPnP-based) [\u003ccode\u003eNetworkService\u003c/code\u003e](http://www.w3.org/TR/2012/WD-discovery-api-20121004/#networkservice)\nobject as the first argument.\n\n    var upnpService = new Plug.UPnP( servicesManager[i] );\n\nHere's a full example, expanding and replacing the \u003ccode\u003esuccessCallback\u003c/code\u003e function we defined earler:\n\n    function successCallback( servicesManager ) {\n\n      // Create a new UPnP object for each service returned\n      var upnpServices = [];\n\n      for( var i = 0; i \u003c servicesManager.length; i++ ) {\n\n        upnpServices.push(\n          new Plug.UPnP( servicesManager[i] )\n        );\n\n        // doUPnPGetMute code provided in Step 3...\n        doUPnPGetMute( upnpServices[ upnpServices.length - 1 ] );\n\n      }\n\n    }\n\nYou can optionally, include a second argument to this constructor to override the default \u003ccode\u003ePlug.UPnP\u003c/code\u003e options:\n\n    new Plug.UPnP( servicesManager[i], { debug: true } )\n\nThe current list of values that can be provided in the options argument are as follows:\n\n###### debug\n\n_Boolean. Whether to spit out more debug messages to the console. Useful when debugging errors in your web app._\n\n#### Step 3: Invoke UPnP actions and process UPnP responses\n\nThe Plug.Play API is built to work on top of [rsvp.js](https://github.com/tildeio/rsvp.js) and therefore provides a  [Promises/A](http://wiki.commonjs.org/wiki/Promises/A)-based interaction model. As part of the Promises model this API supports [method chaining](https://github.com/kriskowal/q#chaining) and [promise sequences](https://github.com/kriskowal/q#sequences).\n\nHere is a simple example of querying the mute state of a UPnP RenderingControl:1 service on a created \u003ccode\u003ePlug.UPnP\u003c/code\u003e object called \u003ccode\u003eupnpService\u003c/code\u003e:\n\n    function doUPnPGetMute( upnpService ) {\n\n      upnpService.action('GetMute', {\n        InstanceId: 0,\n        Channel: 'Master'\n      })\n      .then(function( response ) {\n\n        console.log(\"Service is reporting MUTE=[\" +\n          (response.data.CurrentMute == \"1\" ? 'on' : 'off') +\n            \"]\");\n\n      })\n      .then( null, function( error ) { // All errors will propagate here\n\n        console.log( error.description );\n\n      });\n\n    }\n\nThe Plug.Play library also comes with some convenience classes for particular service types. The demo provided above can also be written against the well-defined [UPnPRenderingControl API](https://github.com/richtr/plug.play.js/tree/master/lib/RenderingControl) also included in this repository. More service-specific wrappers will be added to this repository soon.\n\n### Advanced Usage\n\n##### Type Checking \u0026 Conversion\n\nYou can enforce type checking and type conversion controls in this API according to the data types defined for UPnP in the [UPnP Device Architecture specification](http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf).\n\nThe following code is equivalent to the doUPnPGetMute() function defined above but this time we enforce the variable types and constrain inputs to a series of allowed value types for each input variable:\n\n    function doUPnPGetMute( upnpService ) {\n\n      upnpService.action('GetMute', {\n        InstanceId: {\n          type: upnpService.types.ui4, // or just write 'ui4'\n          value: 0\n        },\n        Channel: {\n          type: upnpService.types.string, // or just write 'string'\n          value: 'Master',\n          allowedValueList:\n            ['Master', 'LF', 'RF', 'CF', 'LFE', 'LS', 'RS',\n                'LFC', 'RFC', 'SD', 'SL', 'SR', 'T', 'B']\n        }\n      })\n      .then(function( response ) {\n\n        console.log(\"Service is reporting MUTE=[\" +\n          (response.data.CurrentMute == \"1\" ? 'on' : 'off' +\n            \"]\");\n\n      })\n      .then( null, function( error ) {\n\n        console.log( \"An error occurred: \" + error.description );\n\n      });\n\n    }\n\nFurthermore, we can use the same structure to enforce variable type conversion on UPnP message response objects. This is useful in particular where we need or want to convert XML types to native JavaScript object types (such as booleans, numbers or dates).\n\nTo do this we supply a more structured argument consisting of two parts: \u003ccode\u003erequest\u003c/code\u003e parameters and \u003ccode\u003eresponse\u003c/code\u003e parameters. We assign our type checking/conversion rules as required in this structure:\n\n    function doUPnPGetMute( upnpService ) {\n\n      upnpService.action('GetMute', {\n        request: {\n          InstanceId: {\n            type: upnpService.types.ui4,\n            value: 0\n          },\n          Channel: {\n            type: upnpService.types.string,\n            value: 'Master',\n            allowedValueList:\n              ['Master', 'LF', 'RF', 'CF', 'LFE', 'LS', 'RS',\n                  'LFC', 'RFC', 'SD', 'SL', 'SR', 'T', 'B']\n          }\n        },\n        response: {\n          CurrentMute: {\n            type: upnpService.types.boolean,\n            value: false // default response value if\n                         // none is provided (optional)\n          }\n        }\n      })\n      .then( function( response ) {\n\n        // Note: we no longer need to check for '== \"1\"' below because\n        // response.data.CurrentMute is now a native JS boolean as we\n        // defined in our \u003cactionParameters\u003e above:\n\n        console.log(\"Service is reporting MUTE=[\" +\n          (response.data.CurrentMute ? 'on' : 'off') +\n            \"]\");\n\n      }, function( error ) { // Handle any errors\n\n        console.log( \"An error occurred: \" + error.description );\n\n      });\n\n    }\n\nPlug.Play API calls can be [chained](https://github.com/kriskowal/q#chaining) as follows:\n\n    function doUPnPGetThenSetThenGetMute( upnpService ) {\n\n      upnpService.action('GetMute', {\n        request: {\n          InstanceId: 0,\n          Channel: 'Master'\n        },\n        response: {\n          CurrentMute: {\n            type: upnpService.types.boolean\n          }\n        }\n      })\n      .then( function( response ) {\n\n        console.log(\"Service is reporting MUTE=[\" +\n          (response.data.CurrentMute ? 'on' : 'off') +\n            \"]\");\n\n        return upnpService.action('SetMute', {\n          request: {\n            InstanceId: 0,\n            Channel: 'Master',\n            DesiredMute: response.data.CurrentMute ? 0 : 1\n          }\n        });\n\n      })\n      .then( function( response ) {\n\n        return upnpService.action('GetMute', {\n          request: {\n            InstanceId: 0,\n            Channel: 'Master'\n          },\n          response: {\n            CurrentMute: {\n              type: upnpService.types.boolean\n            }\n          }\n        })\n\n      })\n      .then( function( response ) {\n\n        console.log(\"Service is reporting MUTE=[\" +\n          (response.data.CurrentMute ? 'on' : 'off') +\n            \"]\");\n\n      })\n      .then( null, function( error ) { // Handle any errors\n\n        console.log( \"An error occurred: \" + error.description );\n\n      });\n\n    }\n\n##### UPnP data types\n\nThe list of valid UPnP data types are as follows:\n\n###### Plug.UPnP.prototype.types.i1\n\n_1 Byte int_\n\n###### Plug.UPnP.prototype.types.i2\n\n_2 Byte int_\n\n###### Plug.UPnP.prototype.types.i4\n\n_4 Byte int_\n\n###### Plug.UPnP.prototype.types.ui1\n\n_Unsigned 1 Byte int_\n\n###### Plug.UPnP.prototype.types.ui2\n\n_Unsigned 2 Byte int_\n\n###### Plug.UPnP.prototype.types.ui4\n\n_Unsigned 4 Byte int_\n\n###### Plug.UPnP.prototype.types.int\n\n_Fixed point, integer number that may have leading sign_\n\n###### Plug.UPnP.prototype.types.r4\n\n_4 Byte float_\n\n###### Plug.UPnP.prototype.types.r8\n\n_8 Byte float_\n\n###### Plug.UPnP.prototype.types.number\n\n_Same as \u003ccode\u003ePlug.UPnP.prototype.types.r8\u003c/code\u003e_\n\n###### Plug.UPnP.prototype.types.fixed\\_14\\_4\n\n_Same as \u003ccode\u003ePlug.UPnP.prototype.types.r8\u003c/code\u003e but no more than 14 digits to the left of the decimal point and no more than 4 to the right_\n\n###### Plug.UPnP.prototype.types.float\n\n_Floating point number (same as \u003ccode\u003ePlug.UPnP.prototype.types.r8\u003c/code\u003e)_\n\n###### Plug.UPnP.prototype.types.char\n\n_Unicode string. One character long_\n\n###### Plug.UPnP.prototype.types.string\n\n_Unicode string. No limit on length_\n\n###### Plug.UPnP.prototype.types.date\n\n_Date without time data (accepts ISO-8601 strings or Date objects and returns ECMA \u003ccode\u003eDate\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.dateTime\n\n_Date with optional time but no time zone (accepts ISO-8601 strings or Date objects and returns ECMA \u003ccode\u003eDate\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.dateTime\\_tz\n\n_Date with optional time and optional time zone (accepts ISO-8601 strings or Date objects and returns ECMA \u003ccode\u003eDate\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.time\n\n_Time with no date and no time zone (accepts ISO-8601 strings or Date objects and returns ECMA \u003ccode\u003eDate\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.time\\_tz\n\n_Time with optional time zone but no date (accepts ISO-8601 strings or Date objects and returns ECMA \u003ccode\u003eDate\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.boolean\n\n_\u003ccode\u003etrue\u003c/code\u003e or \u003ccode\u003efalse\u003c/code\u003e (accepts \u003ccode\u003e'true'\u003c/code\u003e, \u003ccode\u003e'false'\u003c/code\u003e, \u003ccode\u003e'yes'\u003c/code\u003e, \u003ccode\u003e'y'\u003c/code\u003e, \u003ccode\u003e'no'\u003c/code\u003e, \u003ccode\u003e'n'\u003c/code\u003e and returns ECMA \u003ccode\u003eBoolean\u003c/code\u003e objects)_\n\n###### Plug.UPnP.prototype.types.bin\\_base64\n\n_MIME-style Base64 encoded binary blob_\n\n###### Plug.UPnP.prototype.types.bin\\_hex\n\n_Hexadecimal digits representing octets_\n\n###### Plug.UPnP.prototype.types.uri\n\n_Universal Resource Identifier_\n\n###### Plug.UPnP.prototype.types.uuid\n\n_Universally Unique Identifier_\n\n### Feedback\n\nIf you find any bugs or issues please report them on the [Plug.Play Issue Tracker](https://github.com/richtr/plug.play.js/issues).\n\nIf you would like to contribute to this project please consider [forking this repo](https://github.com/richtr/plug.play.js/fork_select) and then creating a new [Pull Request](https://github.com/richtr/plug.play.js/pulls) back to the main code base.\n\n### License\n\nCopyright \u0026copy; 2012 Opera Software ASA\n\nSee the [LICENSE](https://github.com/richtr/plug.play.js/blob/master/LICENSE) file.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichtr%2Fplug.play.js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichtr%2Fplug.play.js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichtr%2Fplug.play.js/lists"}