├── .gitignore
├── LICENSE
├── Readme.md
├── bin
├── hbbtv.js
├── index.js
├── start-cs.js
└── start-terminal.js
├── index.js
├── lib
├── cs-launcher-dial-client.js
├── cs-launcher-dial-server.js
├── hbbtv-app2app-server.js
├── hbbtv-cs-manager.js
├── hbbtv-dial-client.js
├── hbbtv-dial-server.js
├── hbbtv-terminal-manager.js
└── hbbtv.js
├── package.json
├── test
├── app2app-local-client.js
├── app2app-remote-client.js
└── hbbtv-nodejs-client.js
└── www
├── cs-app.html
├── hbbtv-app.html
└── js
├── hbbtv-manager-polyfill.js
└── hbbtvlib.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.project
2 | .idea
3 | node_modules
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | Node.js `hbbtv` module
2 | ====================
3 |
4 | The Node.js `hbbtv` module is a feature complete implementation of the HbbTV 2.0 Companion Screen components:
5 |
6 | * **HbbTV App Launch**: Launching a Companion Screen application from an HbbTV application
7 | * **CS App Launch**: Launching a broadcast independent HbbTV application on an HbbTV terminal from a Companion Screen application.
8 | * **App2App Communication**: Exchange text and binary messages between HbbTV and Companion Screen applications
9 |
10 | Please refer to the [HbbTV 2.0 spec document][hbbtv20spec] for more details especially to the Companion Screen related
11 | sections 8.2.6 and 14.
12 |
13 | The module is developed by the [Fraunhofer FOKUS´s](https://www.fokus.fraunhofer.de/) Competence Center [Future Applications and Media - FAME](https://www.fokus.fraunhofer.de/fame).
14 | Please contact us for more details or if you need help to integrate this module in your product.
15 |
16 | If you find Bugs please submit a new GitHub issue.
17 |
18 | Requirements
19 | ===========
20 |
21 | * [Node.js](https://nodejs.org/). Tested with:
22 | * Node.js v0.12.5 on Windows, Mac and Linux.
23 | * Node.js v0.10.25 on Windows.
24 | * npm (will be installed with Node.js)
25 |
26 | Setup
27 | =====
28 |
29 | * **Install globally**: use `npm install hbbtv -g` to install the module. The `-g` option installs the module globally which is preferred if
30 | the module is used just as CLI. After the module is installed the `hbbtv` command will be available ([Usage section](#usage)
31 | explains how to use the `hbbtv` command). On Mac and Linux you may need to install the module using `sudo npm install hbbtv -g`.
32 | Some optional components require Python 2.7, please ignore related error logs if Python 2.7 is not installed on your machine
33 | or use `npm install hbbtv -g --no-optional` to not install optional components.
34 | * **Update globally installed module**: just run `npm update -g hbbtv`
35 | * **Install locally**: This is not preferred if you want to use the module as CLI. Use `npm install hbbtv` without `-g`
36 | option will create a `node_modules` folder with the `hbbtv` module in it. Please note that the `hbbtv` command will be not
37 | available if you install the module locally. Another way to install locally is to clone this git repository and run `npm install` (or `npm install --no-optional`)
38 | in the home folder to install dependencies. [Usage section](#usage) explains how to use this module if it is installed locally.
39 | * **Update locally installed module**: just run `npm update hbbtv` in the same folder where you installed the module (where you ran `npm install hbbtv`). If the module is cloned from git, run `git pull` and then `npm install`.
40 | * **Integrate in other Node.js applications**: To integrate this module in your Node.js application just add `"hbbtv": ""` (replace `` with the actual version) to
41 | the `dependencies` element of the `package.json` in your application. In your application use `var hbbtv = require("hbbtv")` to
42 | bind the module. For more details about the APIs supported in this module please refer to the [API Documentation](#api-documentation) section.
43 | * **Update module integrated in 3rd party applications**: replace `` with a newer version in `package.json` of your Node.js application
44 |
45 | Usage
46 | =====
47 |
48 | The `hbbtv` module can be started as HbbTV Terminal (`terminal` mode) or as Companion Screen (`cs` mode):
49 |
50 | * If it is started in `terminal` mode, your machine will be seen as a HbbTV 2.0 CS compliant Terminal.
51 | You can use any HbbTV DIAL client to launch HbbTV applications and use any WebSocket client for App2App communication.
52 | The following command can be used to start in `terminal` mode on port `8080`:
53 | * `hbbtv` installed globally
54 |
55 | ```
56 | hbbtv -m terminal -p 8080
57 | ```
58 |
59 | * `hbbtv` installed locally
60 |
61 | ```
62 | cd /path/to/folder/hbbtv/bin
63 | node hbbtv.js -m terminal -p 8080
64 | ```
65 |
66 | * If it is started in `cs` mode, it will turn you machine in a companion screen that runs a CSLauncher and HbbTV DIAL Client.
67 | The HbbTV Terminal started in previous step will be able to discover companion screens running a CSLauncher and to launch CS applications.
68 | Since the discovery and communication between HbbTV terminals and CSLaunchers is not part of the HbbTV 2.0 Spec, we used here also the DIAL
69 | protocol to discover CSLaunchers and launch CS Applications. The CSLauncher acts as DIAL Server that offers a non-stoppable
70 | DIAL application called `Famium` which is already registered in the [DIAL registry][dial-reg]. The application accepts DIAL launch requests
71 | in the body of the related HTTP POST requests in the same format as specified in section
72 | 14.4.2 "Payload format for Install and Launch operations" of the [HbbTV 2.0 spec document][hbbtv20spec].
73 | The following command can be used to start the `hbbtv` module in `cs` mode on port `8090`:
74 |
75 | * `hbbtv` installed globally
76 |
77 | ```
78 | hbbtv -m cs -p 8090
79 | ```
80 |
81 | * `hbbtv` installed locally
82 |
83 | ```
84 | cd /path/to/folder/hbbtv/bin
85 | node hbbtv.js -m cs -p 8090
86 | ```
87 |
88 | * To display `hbbtv` usage options use the following command:
89 |
90 | * `hbbtv` installed globally
91 |
92 | ```
93 | hbbtv -h
94 | ```
95 |
96 | * `hbbtv` installed locally
97 |
98 | ```
99 | cd /path/to/folder/hbbtv/bin
100 | node hbbtv.js -h
101 | ```
102 |
103 | Examples
104 | ========
105 |
106 | Run Example HbbTV App and CS Web App hosted on GitHub
107 | -----------------------------------------------------
108 |
109 | The fastest way to test this module is by using the example HbbTV and CS applications hosted on github.io:
110 | * HbbTV App: `http://fraunhoferfokus.github.io/node-hbbtv/www/hbbtv-app.html`
111 | * CS Web App: `http://fraunhoferfokus.github.io/node-hbbtv/www/cs-app.html`
112 |
113 | ### Run example:
114 |
115 | 1. start `hbbtv` module in `terminal` mode: `hbbtv -m terminal -p 8080`
116 | 2. start `hbbtv` module in `cs` mode: `hbbtv -m cs -p 8090`
117 | > It is possible to start `hbbtv` in `terminal` and `cs` mode on different ports on the same device.
118 | > For better understanding, it is recommended to use two different devices one for `terminal` and one for `cs`. both devices must be
119 | > in the same network in order to discover and communicate with each others using DIAL and WebSocket.
120 |
121 | 3. open CS Web App `http://fraunhoferfokus.github.io/node-hbbtv/www/cs-app.html#port=8090` in a browser on the same device from previous step where `hbbtv` is started in `cs` mode (the port must be the same as in previous step).
122 | 4. follow the instructions in the CS App opened in the browser in previous step: You will be able to discover the HbbTV Terminal started in first step, launch an HbbTV App on it and open a WebSocket communication channel to the remote App2App Endpoint of the discovered terminal.
123 | 5. After the HbbTV App is launched on the terminal, it will be able to discover CSLaunchers, launch CS Web Apps and create WebSocket communication channels to the local App2App Endpoint.
124 |
125 | Develop HbbTV App
126 | -----------------
127 |
128 | * The following example shows an HbbTV Application that discovers CSLaunchers, launches a CS Web App on a discovered CSLauncher and creates
129 | a WebSocket connection to the local App2App Endpoint. The following steps are needed to run this example:
130 | * Start `hbbtv` in `terminal` mode: `hbbtv -m terminal -p 8080`
131 | * Please don't open this application manually in the Browser. Use the example CS Web App described in next subsection to launch this application.
132 | * The HbbTV Web App needs to include the JavaScript Lib `hbbtv-manager-polyfill.js`
133 | * Please refer to section 8.2.6 of the HbbTV 2.0 Spec document for more details about the JavaScript API of the HbbTVCSManager.
134 |
135 | ```html
136 |
137 |
138 |
139 |
140 |
141 | HbbTV App
142 |
143 |
144 |
145 |
209 |
210 |
211 | ```
212 |
213 | Develop Companion Screen Web App
214 | --------------------------------
215 |
216 | * The following example show a CS Web Application that discovers HbbTV Terminals, launches an HbbTV App on a discovered terminal and creates
217 | a WebSocket connection to the App2App Endpoint of the discovered Terminal. The following steps are needed to run this example:
218 | * Start `hbbtv` in `cs` mode: `hbbtv -m cs -p 8090`
219 | * Open the CS Web App in a Browser on the same device and append `#port=8090` to the URL: `http://www.example.com/cs-app.html#port=8090`
220 | * The CS Web App needs to include the JavaScript Lib `hbbtv-manager-polyfill.js`
221 | * The following example uses all JavaScript functions required to discover terminals, launch HbbTV Apps and create WebSocket connection.
222 | API documentation coming soon.
223 |
224 | ```html
225 |
226 |
227 |
228 |
229 |
230 | Companion Screen App
231 |
232 |
233 |
234 |
299 |
300 |
301 | ```
302 |
303 | Develop Node.js HbbTV CS Client
304 | -------------------------------
305 |
306 | the `hbbtv` module can also used to implement HbbTV CS Node.js clients without the need to develop CS Web App that runs
307 | in the Browser. This is for example useful to run HbbTV CS test cases or to use in Node.js applications to discover HbbTV
308 | terminals, launch HbbTV applications and create WebSocket connections to the remote App2App Endpoint of discovered terminals.
309 | The following example illustrates the usage of supported features
310 |
311 | ```javascript
312 | var hbbtv = require("hbbtv");
313 | var HbbTVDialClient = hbbtv.HbbTVDialClient;
314 | var WebSocket = hbbtv.WebSocket;
315 | // create a hbbTVDialClient instance and add listeners for ready, stop, found and error events
316 | var hbbTVDialClient = new HbbTVDialClient().on("ready", function () {
317 | console.log("HbbTV DIAL Client is ready");
318 | }).on("stop", function () {
319 | console.log("HbbTV DIAL Client is stopped");
320 | }).on("found", function (terminal) {
321 | // found events are triggered each time a new HbbTV terminal is found
322 | console.log("HbbTV Terminal ", terminal.getFriendlyName()," (", terminal.getAppLaunchURL(), ") found");
323 | var channel = (""+Math.random()).substr(2,16);
324 | // launch HbbTV App on each discovered terminal
325 | terminal.launchHbbTVApp({
326 | "appUrlBase": "http://fraunhoferfokus.github.io/node-hbbtv/www/hbbtv-app.html",
327 | "appLocation": "?channel="+channel
328 | }, function (launchRes,err) {
329 | if(err){
330 | console.error("Error on launch HbbTV App", err);
331 | }
332 | else {
333 | console.log("HbbTV App launched successfully: ",launchRes || "");
334 | // create App2App connection after application is launched
335 | createConnection(terminal, channel);
336 | }
337 | });
338 | }).on("error", function (err) {
339 | console.error(err);
340 | });
341 | var createConnection = function (terminal, channel) {
342 | var app2appRemoteBaseUrl = terminal.getApp2AppURL();
343 | var ws = new WebSocket(app2appRemoteBaseUrl + channel);
344 | ws.binaryType = "arraybuffer";
345 | ws.onopen = function(evt) {
346 | console.log("Connection waiting ...");
347 | };
348 | ws.onclose = function(evt) {
349 | console.log("Connection closed.");
350 | };
351 | ws.onerror = function (evt) {
352 | console.log("Connection error.");
353 | };
354 | ws.onmessage = function(evt) {
355 | if (evt.data == "pairingcompleted") {
356 | console.log("pairing complete");
357 | ws.onmessage = function(evt) {
358 | console.log( "Received Message: " + evt.data);
359 | };
360 | var data = "Hello from Companion Screen";
361 | ws.send(data);
362 | var array = [0,1,2,3,4,5,6,7,8,9];
363 | data = typeof Buffer != "undefined"?new Buffer(array): new Int8Array(array).buffer;
364 | ws.send(data);
365 | } else {
366 | console.log("Unexpected message received from terminal.");
367 | ws.close();
368 | }
369 | };
370 | };
371 | hbbTVDialClient.start();
372 | // hbbTVDialClient.stop();
373 | ```
374 |
375 | Android HbbTV CS Client
376 | -----------------
377 | Please contact us for more details
378 |
379 | iOS HbbTV CS Client
380 | -------------
381 | Please contact us for more details
382 |
383 | Cordova HbbTV CS Client
384 | -----------------
385 | Please contact us for more details
386 |
387 | API Documentation
388 | =================
389 |
390 | The Node.js `hbbtv` module is designed to be integrated in existing products like set-top-boxes or TV sets with Node.js
391 | environment. The current implementation launches HbbTV and Companion Screen applications in the default browser. This is
392 | practicable to test HbbTV 2.0 CS features on the same environment developers use to develop their applications. To
393 | use this module in real products, the HbbTV UA needs to be launched instead of the default browser. This can be easily done
394 | by making the HbbTV UA as default Browser or just by starting it directly from this module just by replacing the lines of
395 | code where the default Browser is launched with your launch command.
396 |
397 | API documentation for the `hbbtv-manager-polyfill.js` and the `hbbtv` module and its sub-components coming soon.
398 |
399 | Contribution
400 | ============
401 |
402 | We are grateful for any valuable contribution, like [issue reports](https://github.com/fraunhoferfokus/node-hbbtv/issues),
403 | [tests](https://github.com/fraunhoferfokus/node-hbbtv/tree/master/test) or [pull requests](https://github.com/fraunhoferfokus/node-hbbtv/pulls).
404 |
405 | Moreover, we would love to hear which exciting apps you have created using the `hbbtv` Node.js module.
406 |
407 | License
408 | =======
409 |
410 | Free for non commercial use released under the GNU Lesser General Public License v3.0, See LICENSE file.
411 |
412 | Contact us for commercial use
413 |
414 | Copyright (c) 2015 [Fraunhofer FOKUS](https://www.fokus.fraunhofer.de/)
415 |
416 | Contact
417 | =======
418 |
419 | * [Fraunhofer FOKUS - Competence Center FAME // Future Applications and Media](http://www.fokus.fraunhofer.de/fame)
420 | *
421 |
422 | [hbbtv20spec]: http://www.hbbtv.org/wp-content/uploads/2015/07/HbbTV-SPEC20-00023-001-HbbTV_2.0.1_specification_for_publication_clean.pdf
423 | [dial-reg]: http://www.dial-multiscreen.org/dial-registry/namespace-database#TOC-Registered-Names
424 |
--------------------------------------------------------------------------------
/bin/hbbtv.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var program = require("commander");
22 | var package = require("../package.json");
23 | program.version(package.version)
24 | .allowUnknownOption(false)
25 | .option("-m, --mode ", "select mode. It is either 'terminal' to start as HbbTV Terminal or 'cs' to start as Companion Screen", /^(terminal|cs)$/i)
26 | .option("-p, --port ", "specify the port number of the HbbTV Terminal or CS Launcher. e.g. 8080",parseInt)
27 | .option("-i, --interdevsync-url ", "specify the URL of the inter-device synchronisation CSS-CII server. Applies to 'terminal' mode only. '{hostname}' substring will be replaced with the hostname of this server, as viewed by the client. Optional.")
28 | .option("-u, --useragent ", "specify the user agent string to be advertised. Applies to 'terminal' mode only. Optional.")
29 | .option("-o, --opn-args ", "specify the arguments to opn (used for launching apps), separated by | characters. e.g. firefox|-no-remote. Optional.")
30 | .option("-f, --friendly-name ", "specify the device name to be advertised (overriding system hostname). Applies to 'terminal' mode only. Optional.")
31 |
32 | program.parse(process.argv);
33 | var port = program.port>0 && program.port || null;
34 | var mode = program.mode || null;
35 | var interDevSyncUrl = program["interdevsyncUrl"] || null;
36 | var userAgent = program["useragent"] || null;
37 | var opn_params = program["opnArgs"] ? program["opnArgs"].split('|') : undefined;
38 | var friendlyName = program["friendlyName"] || null;
39 |
40 | if(port){
41 | global.PORT = port;
42 | global.OPN_PARAMS = opn_params;
43 | if(mode == "terminal"){
44 | global.INTERDEVSYNC_URL = interDevSyncUrl;
45 | global.USERAGENT = userAgent;
46 | global.FRIENDLY_NAME = friendlyName;
47 | require("./start-terminal.js");
48 | }
49 | else if(mode == "cs"){
50 | require("./start-cs.js");
51 | }
52 | else {
53 | program.help();
54 | }
55 | }
56 | else{
57 | program.help();
58 | }
59 |
--------------------------------------------------------------------------------
/bin/index.js:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 | /*******************************************************************************
3 | *
4 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 3.0 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library. If not, see .
18 | *
19 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
20 | *
21 | ******************************************************************************/
22 | require("./hbbtv.js");
--------------------------------------------------------------------------------
/bin/start-cs.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var PORT = global.PORT;
22 | if(!PORT){
23 | console.log("variable 'global.PORT' is missing or not a valid port");
24 | process.exit(1);
25 | }
26 | var hbbtv = require("../index.js");
27 | var HbbTVTerminalManager = hbbtv.HbbTVTerminalManager;
28 | var CsLauncherDialServer = hbbtv.CsLauncherDialServer;
29 | var http = require('http');
30 | var express = require("express");
31 | var app = express();
32 | var DIAL_PREFIX = "/dial";
33 | app.set("port",PORT);
34 | app.set("dial-prefix",DIAL_PREFIX);
35 | http.globalAgent.maxSockets = 100;
36 | var counter = 0;
37 | var httpServer = http.createServer(app);
38 |
39 | var csLauncherDialServer = new CsLauncherDialServer(app).on("ready", function () {
40 | console.log("HbbTV CS Launcher is ready");
41 | counter++;
42 | }).on("stop", function () {
43 | console.log("HbbTV CS Launcher is stopped");
44 | if(--counter == 0){
45 | process.exit();
46 | }
47 | }).on("error", function (err) {
48 | console.error(err);
49 | });
50 |
51 | var hbbTVTerminalManager = new HbbTVTerminalManager(httpServer).on("ready", function () {
52 | counter++;
53 | console.log("HbbTV Terminal Manager is ready");
54 | }).on("stop", function () {
55 | console.log("HbbTV Terminal Manager is stopped");
56 | if(--counter == 0){
57 | process.exit();
58 | }
59 | }).on("error", function (err) {
60 | console.error(err);
61 | });
62 |
63 | httpServer.listen(PORT, function() {
64 | console.log("HbbTV Companion Screen is listening on port ", PORT);
65 | //console.log("***** Please append the hash query '#port="+PORT+"'"," to the URL of your CS Web App.\n***** The JavaScript Lib 'hbbtv-manager-polyfill.js' must be included in the CS Web App");
66 | hbbTVTerminalManager.start();
67 | csLauncherDialServer.start();
68 | });
69 |
70 | process.on('SIGINT', function() {
71 | console.log("Stopping HbbTV Companion Screen. Please wait ...");
72 | hbbTVTerminalManager.stop();
73 | csLauncherDialServer.stop();
74 | setTimeout(function () {
75 | process.exit();
76 | },3000);
77 | });
--------------------------------------------------------------------------------
/bin/start-terminal.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2013 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var PORT = global.PORT;
22 | var INTERDEVSYNC_URL = global.INTERDEVSYNC_URL;
23 | var USERAGENT = global.USERAGENT;
24 | var OPN_PARAMS = global.OPN_PARAMS;
25 | if(!PORT){
26 | console.log("variable 'global.PORT' is missing or not a valid port");
27 | process.exit(1);
28 | }
29 | var hbbtv = require("../index.js");
30 | var HbbTVApp2AppServer = hbbtv.HbbTVApp2AppServer;
31 | var HbbTVDialServer = hbbtv.HbbTVDialServer;
32 | var HbbTVCsManager = hbbtv.HbbTVCsManager;
33 | var http = require('http');
34 | var express = require("express");
35 | var app = express();
36 | var DIAL_PREFIX = "/dial";
37 | var CS_MANAGER_PREFIX = "/csmanager";
38 | http.globalAgent.maxSockets = 100;
39 | var counter = 0;
40 | app.set("port",PORT);
41 | app.set("dial-prefix",DIAL_PREFIX);
42 | app.set("cs-manager-prefix", CS_MANAGER_PREFIX);
43 | app.set("inter-dev-sync-url", INTERDEVSYNC_URL);
44 | app.set("user-agent", USERAGENT);
45 | app.set("opn-params", OPN_PARAMS);
46 | // The HTTP Server is used to in the HbbTVApp2AppServer and the HbbTVDialServer
47 | var httpServer = http.createServer(app);
48 |
49 | var hbbtvApp2AppServer = new HbbTVApp2AppServer(httpServer).on("ready", function () {
50 | console.log("HbbTV App2App Server is ready");
51 | counter++;
52 | }).on("stop", function () {
53 | console.log("HbbTV App2App Server is stopped");
54 | if(--counter == 0){
55 | process.exit();
56 | }
57 | }).on("error", function (err) {
58 | console.error("HbbTVApp2AppServer Error", err);
59 | });
60 |
61 | var hbbtvDialServer = new HbbTVDialServer(app).on("ready", function () {
62 | console.log("HbbTV DIAL Server is ready");
63 | counter++;
64 | }).on("stop", function () {
65 | console.log("HbbTV DIAL Server is stopped");
66 | if(--counter == 0){
67 | process.exit();
68 | }
69 | }).on("error", function (err) {
70 | console.error("HbbTVDialServer Error", err);
71 | });
72 |
73 | var hbbTVCsManager = new HbbTVCsManager(httpServer).on("ready", function () {
74 | console.log("HbbTV CS Manager is ready");
75 | counter++;
76 | }).on("stop", function () {
77 | console.log("HbbTV CS Manager is stopped");
78 | if(--counter == 0){
79 | process.exit();
80 | }
81 | }).on("error", function (err) {
82 | console.error("HbbTVCSManager Error", err);
83 | });
84 |
85 | httpServer.listen(PORT, function() {
86 | console.log("HbbTV Terminal is listening on port ", PORT);
87 | //console.log("***** The JavaScript Lib 'hbbtv-manager-polyfill.js' must be included in the HbbTV App");
88 | hbbtvApp2AppServer.start();
89 | hbbtvDialServer.start();
90 | hbbTVCsManager.start();
91 | });
92 |
93 | process.on('SIGINT', function() {
94 | console.log("Stopping HbbTV Terminal. Please wait ...");
95 | hbbtvApp2AppServer.stop();
96 | hbbtvDialServer.stop();
97 | hbbTVCsManager.stop();
98 | setTimeout(function () {
99 | process.exit();
100 | },3000);
101 | });
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2013 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | module.exports = require('./lib/hbbtv');
--------------------------------------------------------------------------------
/lib/cs-launcher-dial-client.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var dial = require("peer-dial");
22 | var util = require("util");
23 | var events = require("events");
24 |
25 | var CsLauncher = function (dialDevice, appInfo) {
26 | var appLaunchURL = dialDevice && dialDevice.applicationUrl && (dialDevice.applicationUrl+"/Famium") || null;
27 | var osId = appInfo && appInfo.additionalData && appInfo.additionalData.X_FAMIUM_CS_OS_ID || null;
28 |
29 | dialDevice && (dialDevice.appLaunchURL = appLaunchURL);
30 | dialDevice && (dialDevice.osId = osId);
31 |
32 | var getAppLaunchURL = function () {
33 | return appLaunchURL;
34 | };
35 |
36 | var getInfo = function () {
37 | return dialDevice || null;
38 | };
39 |
40 | var launchCsApp = function (launchData,callback) {
41 | var launchReq = launchData;
42 | dialDevice.launchApp("Famium",launchReq, "text/plain", function (launchRes, err) {
43 | if(typeof launchRes != "undefined"){
44 | callback && callback(launchRes,err);
45 | }
46 | else if(err){
47 | callback && callback(null,err);
48 | }
49 | });
50 | };
51 |
52 | Object.defineProperty(this,"launchCsApp", {
53 | get: function(){
54 | return launchCsApp;
55 | }
56 | });
57 |
58 | Object.defineProperty(this,"getInfo", {
59 | get: function(){
60 | return getInfo;
61 | }
62 | });
63 |
64 | Object.defineProperty(this,"getAppLaunchURL", {
65 | get: function(){
66 | return getAppLaunchURL;
67 | }
68 | });
69 | };
70 |
71 | var CsLauncherDialClient = function () {
72 | var dialClient = new dial.Client();
73 | var self = this;
74 | var csLaunchers = {};
75 | dialClient.on("ready",function(){
76 | self.emit("ready");
77 | }).on("found",function(deviceDescriptionUrl, headers){
78 | dialClient.getDialDevice(deviceDescriptionUrl, function (dialDevice, err) {
79 | if(dialDevice){
80 | dialDevice.getAppInfo("Famium", function (appInfo, err) {
81 | if(appInfo){
82 | var csLauncher = new CsLauncher(dialDevice, appInfo);
83 | csLaunchers[deviceDescriptionUrl] = csLauncher;
84 | self.emit("found", csLauncher);
85 | }
86 | else if(err){
87 | // TODO check if this is an error or not
88 | //var error = new Error("Error on get CS Launcher FAMIUM App Info or DIAL device is not a FAMIUM CS Launcher", err.message);
89 | //self.emit("error", error);
90 | }
91 | });
92 | }
93 | else if(err){
94 | var error = new Error("Error on get device description from "+deviceDescriptionUrl, err.message);
95 | self.emit("error", error);
96 | }
97 | });
98 | }).on("disappear", function(deviceDescriptionUrl, headers){
99 | var csLauncher = csLaunchers[deviceDescriptionUrl];
100 | delete csLaunchers[deviceDescriptionUrl];
101 | self.emit("disappear",deviceDescriptionUrl, csLauncher);
102 | }).on("stop", function(){
103 | self.emit("stop");
104 | }).on("error", function (err) {
105 | self.emit("error",err);
106 | });
107 |
108 | var start = function () {
109 | dialClient.start();
110 | return this;
111 | };
112 |
113 | var refresh = function () {
114 | dialClient.refresh();
115 | return this;
116 | };
117 |
118 | var stop = function () {
119 | dialClient.stop();
120 | return this;
121 | };
122 |
123 | Object.defineProperty(this,"start", {
124 | get: function(){
125 | return start;
126 | }
127 | });
128 |
129 | Object.defineProperty(this,"refresh", {
130 | get: function(){
131 | return refresh;
132 | }
133 | });
134 |
135 | Object.defineProperty(this,"stop", {
136 | get: function(){
137 | return stop;
138 | }
139 | });
140 | };
141 |
142 | util.inherits(CsLauncherDialClient, events.EventEmitter);
143 | module.exports = CsLauncherDialClient;
--------------------------------------------------------------------------------
/lib/cs-launcher-dial-server.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var HbbTVDialServer = require("./hbbtv-dial-server.js");
22 | var util = require("util");
23 |
24 | var CsLauncherDialServer = function (expressApp) {
25 | var isCsLauncher = true;
26 | HbbTVDialServer.call(this,expressApp,isCsLauncher);
27 | };
28 |
29 | util.inherits(CsLauncherDialServer, HbbTVDialServer);
30 | module.exports = CsLauncherDialServer;
--------------------------------------------------------------------------------
/lib/hbbtv-app2app-server.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var ws = require("ws");
22 | var util = require("util");
23 | var events = require("events");
24 | var WebSocketServer = ws.Server;
25 | var HbbTVApp2AppServer = function (httpServer) {
26 | var wsServer = null;
27 | var pendingLocalConnections = null;
28 | var pendingRemoteConnections = null;
29 | var handlePendingConnectionsChanged = function (channel) {
30 | var channelPendingLocalConnections = pendingLocalConnections[channel] || [];
31 | var channelPendingRemoteConnections = pendingRemoteConnections[channel] || [];
32 | while(channelPendingLocalConnections.length>0 && channelPendingRemoteConnections.length>0){
33 | var localConnection = channelPendingLocalConnections.pop();
34 | var remoteConnection = channelPendingRemoteConnections.pop();
35 | localConnection.pair = remoteConnection;
36 | remoteConnection.pair = localConnection;
37 | localConnection && (localConnection.readyState == ws.OPEN) && localConnection.send("pairingcompleted");
38 | remoteConnection && (remoteConnection.readyState == ws.OPEN) && remoteConnection.send("pairingcompleted");
39 | }
40 | if(channelPendingLocalConnections.length == 0){
41 | delete pendingLocalConnections[channel];
42 | }
43 | if(channelPendingRemoteConnections.length == 0){
44 | delete pendingRemoteConnections[channel];
45 | }
46 | };
47 | var handleConnectionClosed = function (connection) {
48 | if(connection.local) {
49 | var channelPendingLocalConnections = pendingLocalConnections[connection.channel] || [];
50 | var index = channelPendingLocalConnections.indexOf(connection);
51 | index >= 0 && channelPendingLocalConnections.splice(index, 1);
52 | if(channelPendingLocalConnections.length == 0){
53 | delete pendingLocalConnections[connection.channel];
54 | }
55 | }
56 | else if(connection.remote){
57 | var channelPendingRemoteConnections = pendingRemoteConnections[connection.channel] || [];
58 | var index = channelPendingRemoteConnections.indexOf(connection);
59 | index >= 0 && pendingRemoteConnections.splice(index, 1);
60 | if(channelPendingRemoteConnections.length == 0){
61 | delete pendingRemoteConnections[connection.channel];
62 | }
63 | }
64 | };
65 |
66 | var handleConnectionReceived = function(connection) {
67 | var req = connection.upgradeReq;
68 | if(req.channel){
69 | var channel = req.channel;
70 | connection.channel = channel;
71 | if(req.local){
72 | connection.local = true;
73 | var channelPendingLocalConnections = pendingLocalConnections[channel] || (pendingLocalConnections[channel] = []);
74 | channelPendingLocalConnections.push(connection);
75 | }
76 | else {
77 | connection.remote = true;
78 | var channelPendingRemoteConnections = pendingRemoteConnections[channel] || (pendingRemoteConnections[channel] = []);
79 | channelPendingRemoteConnections.push(connection);
80 | }
81 | handlePendingConnectionsChanged(channel);
82 | connection.on("message", function(msg, flags) {
83 | var options = {};
84 | flags.binary && (options.binary = true);
85 | flags.masked && (options.masked = true);
86 | if (flags && flags.binary) {
87 | connection.pair && (connection.pair.readyState == ws.OPEN) && connection.pair.send(msg, options);
88 | }
89 | else {
90 | connection.pair && (connection.pair.readyState == ws.OPEN) && connection.pair.send(msg, options);
91 | }
92 | });
93 | connection.on("close", function(code, reason) {
94 | if(connection.pair){
95 | connection.pair.close();
96 | connection.pair = null;
97 | }
98 | else {
99 | handleConnectionClosed(connection);
100 | }
101 | connection = null;
102 | });
103 | connection.on("error", function () {
104 | // TODO handle error and remove socket
105 | });
106 | }
107 | else {
108 | connection.close();
109 | }
110 | };
111 |
112 | var verifyClient = function (info,callback) {
113 | var req = info.req;
114 | var url = req.url || "";
115 | var channel = null;
116 | var verified;
117 | var code;
118 | if(url.indexOf("/local/") == 0){
119 | channel = url.substr(7) || null;
120 | req.local = true;
121 | }
122 | else if(url.indexOf("/remote/") == 0){
123 | channel = url.substr(8) || null;
124 | req.local = false;
125 | }
126 | if(channel){
127 | req.channel = channel;
128 | verified = true;
129 | callback && callback(verified);
130 | }
131 | /*else{
132 | verified = false;
133 | code = 400;
134 | }
135 | try{
136 | callback(verified,code);
137 | }
138 | catch (e){
139 | console.error("Error on verify client",e);
140 | }*/
141 | };
142 |
143 | var reset = function () {
144 | wsServer && wsServer.close();
145 | wsServer = null;
146 | pendingLocalConnections = [];
147 | pendingRemoteConnections = [];
148 | };
149 |
150 | var start = function () {
151 | reset();
152 | wsServer = new WebSocketServer({
153 | server: httpServer,
154 | verifyClient : verifyClient
155 | }).on("connection", handleConnectionReceived);
156 | this.emit("ready");
157 | return this;
158 | };
159 |
160 | var stop = function () {
161 | reset();
162 | this.emit("stop");
163 | return this;
164 | };
165 |
166 | Object.defineProperty(this,"start", {
167 | get: function(){
168 | return start;
169 | }
170 | });
171 |
172 | Object.defineProperty(this,"stop", {
173 | get: function(){
174 | return stop;
175 | }
176 | });
177 | };
178 |
179 | util.inherits(HbbTVApp2AppServer, events.EventEmitter);
180 |
181 | module.exports = HbbTVApp2AppServer;
--------------------------------------------------------------------------------
/lib/hbbtv-cs-manager.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var dial = require("peer-dial");
22 | var util = require("util");
23 | var events = require("events");
24 | var CsLauncherDialClient = require("./cs-launcher-dial-client.js");
25 | var HbbTVDialClient = require("./hbbtv-dial-client.js");
26 | var ws = require("ws");
27 | var WebSocketServer = ws.Server;
28 | var enableCORS = function(req, res, next) {
29 | res.header("Access-Control-Allow-Origin", "*");
30 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Application-URL");
31 | next();
32 | };
33 |
34 | var HbbTVCSManager = function (httpServer, isCs) {
35 | //var prefix = expressApp.get("cs-manager-prefix") || "";
36 | isCs = (isCs == true);
37 | var csLauncherDialClient = new CsLauncherDialClient();
38 | var hbbTVDialClient = new HbbTVDialClient();
39 | var self = this;
40 | var wsServer = null;
41 | var csLaunchers = {};
42 | var tmpCsLaunchers = {};
43 | var terminals = {};
44 | var tmpTerminals = {};
45 | var lastCsLauncherRefresh = 0;
46 | var lastHbbTVTerminalRefresh = 0;
47 | var discoveryTime = 5000;
48 | var readyCounter = isCs?1:0;
49 | var stopCounter = isCs?1:0;
50 | csLauncherDialClient.on("ready",function(){
51 | readyCounter++ && self.emit("ready");
52 | }).on("found",function(csLauncher){
53 | csLaunchers[csLauncher.getAppLaunchURL()] = csLauncher;
54 | tmpCsLaunchers[csLauncher.getAppLaunchURL()] = csLauncher.getInfo();
55 | }).on("disappear", function(deviceDescriptionUrl, csLauncher){
56 | delete csLaunchers[deviceDescriptionUrl];
57 | delete tmpCsLaunchers[deviceDescriptionUrl];
58 | }).on("stop", function(){
59 | stopCounter++ && self.emit("stop");
60 | }).on("error", function (err) {
61 | self.emit("error",err);
62 | });
63 |
64 | hbbTVDialClient.on("ready",function(){
65 | readyCounter++ && self.emit("ready");
66 | }).on("found",function(terminal){
67 | terminals[terminal.getAppLaunchURL()] = terminal;
68 | tmpTerminals[terminal.getAppLaunchURL()] = terminal.getInfo();
69 | }).on("disappear", function(deviceDescriptionUrl, terminal){
70 | delete terminals[deviceDescriptionUrl];
71 | delete tmpTerminals[deviceDescriptionUrl];
72 | }).on("stop", function(){
73 | stopCounter++ && self.emit("stop");
74 | }).on("error", function (err) {
75 | self.emit("error",err);
76 | });
77 |
78 | var handleConnectionReceived = function(connection) {
79 | connection.on("message", function(msg, flags) {
80 | // expect msg as jsonrpc request
81 | if(typeof msg == "string"){
82 | try{
83 | var req = JSON.parse(msg);
84 | var method = req.method;
85 | if(method == "discoverCSLaunchers"){
86 | discoverCSLaunchers(connection,req);
87 | }
88 | else if(method == "discoverTerminals"){
89 | discoverTerminals(connection,req);
90 | }
91 | else if(method == "launchCSApp"){
92 | launchCSApp(connection,req);
93 | }
94 | else if(method == "launchHbbTVApp"){
95 | launchHbbTVApp(connection,req);
96 | }
97 | }
98 | catch(err){
99 | self.emit("error",err);
100 | }
101 | }
102 | }).on("close", function(code, reason) {
103 |
104 | });
105 | };
106 |
107 | var verifyClient = function (info,callback) {
108 | var req = info.req;
109 | var url = req.url || "";
110 | if(url == "/hbbtvmanager"){
111 | callback && callback(true);
112 | }
113 | /*else {
114 | callback && callback(false,400);
115 | }*/
116 | };
117 |
118 | var discoverCSLaunchers = function (connection, req) {
119 | var currentTime = new Date().getTime();
120 | var timeElapsed = currentTime - lastCsLauncherRefresh;
121 | var timeout = 0;
122 | if(timeElapsed > discoveryTime){
123 | lastCsLauncherRefresh = currentTime;
124 | tmpCsLaunchers = {};
125 | csLauncherDialClient.refresh();
126 | timeout = discoveryTime;
127 | }
128 | else {
129 | timeout = discoveryTime-timeElapsed;
130 | }
131 | setTimeout(function(){
132 | var rsp = {
133 | "jsonrpc": "2.0",
134 | "result": tmpCsLaunchers,
135 | "id": req.id
136 | };
137 | connection.send(JSON.stringify(rsp));
138 | }, timeout);
139 | };
140 |
141 | var launchCSApp = function (connection, req) {
142 | var launcherId = req.params[0];
143 | var payload = req.params[1];
144 | var csLauncher = csLaunchers[launcherId];
145 | var code = null;
146 | // TODO check payload if it is conform with the HbbTV 2.0 Spec as described in 14.4.2
147 | if(csLauncher){
148 | csLauncher.launchCsApp(payload, function (launchRes, err) {
149 | if(err){
150 | code = 400;
151 | }
152 | else {
153 | code = 200;
154 | }
155 | });
156 | }
157 | else {
158 | code = 404;
159 | }
160 | var rsp = {
161 | "jsonrpc": "2.0",
162 | "result": code,
163 | "id": req.id
164 | };
165 | connection.send(JSON.stringify(rsp));
166 | };
167 |
168 | var discoverTerminals = function (connection, req) {
169 | var currentTime = new Date().getTime();
170 | var timeElapsed = currentTime - lastHbbTVTerminalRefresh;
171 | var timeout = 0;
172 | if(timeElapsed > discoveryTime){
173 | lastHbbTVTerminalRefresh = currentTime;
174 | tmpTerminals = {};
175 | hbbTVDialClient.refresh();
176 | timeout = discoveryTime;
177 | }
178 | else {
179 | timeout = discoveryTime-timeElapsed;
180 | }
181 | setTimeout(function(){
182 | var rsp = {
183 | "jsonrpc": "2.0",
184 | "result": tmpTerminals,
185 | "id": req.id
186 | };
187 | connection.send(JSON.stringify(rsp));
188 | }, timeout);
189 | };
190 |
191 | var launchHbbTVApp = function (connection, req) {
192 | var terminalId = req.params[0];
193 | var options = req.params[1];
194 | var terminal = terminals[terminalId];
195 | var code = null;
196 | // TODO check options object
197 | if(terminal){
198 | terminal.launchHbbTVApp(options, function (launchRes, err) {
199 | if(err){
200 | code = 400;
201 | }
202 | else {
203 | code = 200;
204 | }
205 | });
206 | }
207 | else {
208 | code = 404;
209 | }
210 | var rsp = {
211 | "jsonrpc": "2.0",
212 | "result": code,
213 | "id": req.id
214 | };
215 | connection.send(JSON.stringify(rsp));
216 | };
217 |
218 | var start = function () {
219 | !isCs && csLauncherDialClient.start();
220 | hbbTVDialClient.start();
221 | wsServer = new WebSocketServer({
222 | server: httpServer,
223 | verifyClient : verifyClient
224 | }).on("connection", handleConnectionReceived);
225 | return this;
226 | };
227 |
228 | var stop = function () {
229 | !isCs && csLauncherDialClient.stop();
230 | hbbTVDialClient.stop();
231 | wsServer.close();
232 | return this;
233 | };
234 |
235 | Object.defineProperty(this,"start", {
236 | get: function(){
237 | return start;
238 | }
239 | });
240 |
241 | Object.defineProperty(this,"stop", {
242 | get: function(){
243 | return stop;
244 | }
245 | });
246 | };
247 |
248 | util.inherits(HbbTVCSManager, events.EventEmitter);
249 |
250 | module.exports = HbbTVCSManager;
--------------------------------------------------------------------------------
/lib/hbbtv-dial-client.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var dial = require("peer-dial");
22 | var util = require("util");
23 | var events = require("events");
24 | var URL = require("url");
25 | var builder = require('xmlbuilder');
26 |
27 | var HbbTVTerminal = function (dialDevice, appInfo) {
28 |
29 | var appLaunchURL = dialDevice && dialDevice.applicationUrl && (dialDevice.applicationUrl+"/HbbTV") || null;
30 | var app2AppURL = appInfo && appInfo.additionalData && appInfo.additionalData.X_HbbTV_App2AppURL || null;
31 | var interDevSyncURL = appInfo && appInfo.additionalData && appInfo.additionalData.X_HbbTV_InterDevSyncURL || null;
32 | var userAgent = appInfo && appInfo.additionalData && appInfo.additionalData.X_HbbTV_UserAgent || null;
33 | var friendlyName = dialDevice && dialDevice.friendlyName || null;
34 | dialDevice && (dialDevice.appLaunchURL = appLaunchURL);
35 | dialDevice && (dialDevice.app2AppURL = app2AppURL);
36 | dialDevice && (dialDevice.userAgent = userAgent);
37 | dialDevice && (dialDevice.interDevSyncURL = interDevSyncURL);
38 |
39 | var getInfo = function () {
40 | return dialDevice || null;
41 | };
42 | var getApp2AppURL = function () {
43 | return app2AppURL;
44 | };
45 | var getInterDevSyncURL = function () {
46 | return interDevSyncURL;
47 | };
48 | var getUserAgent = function () {
49 | return userAgent;
50 | };
51 | var getAppLaunchURL = function () {
52 | return appLaunchURL;
53 | };
54 | var getFriendlyName = function () {
55 | return friendlyName;
56 | };
57 |
58 | var launchHbbTVApp = function (launchData,callback) {
59 | var orgId = launchData.orgId || "";
60 | var appId = launchData.appId || "";
61 | var appName = launchData.appName || "";
62 | var appNameLanguage = launchData.appNameLanguage || "";
63 | var appUrlBase = launchData.appUrlBase || "";
64 | var appLocation = launchData.appLocation || "";
65 | var appUrl = URL.parse(appUrlBase);
66 | if(appUrl.protocol && appUrl.hostname){
67 | var mhp = {
68 | "mhp:ServiceDiscovery": {
69 | "@xmlns:mhp": "urn:dvb:mhp:2009",
70 | "@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
71 | "mhp:ApplicationDiscovery": {
72 | "@DomainName": appUrl.hostname,
73 | "mhp:ApplicationList": {
74 | "mhp:Application": {
75 | "mhp:appName": {
76 | "@Language": appNameLanguage,
77 | "#text": appName
78 | },
79 | "mhp:applicationIdentifier": {
80 | "mhp:orgId": orgId,
81 | "mhp:appId": appId
82 | },
83 | "mhp:applicationDescriptor": {
84 | "mhp:type": {
85 | "mhp:OtherApp": "application/vnd.hbbtv.xhtml+xml"
86 | },
87 | "mhp:controlCode": "AUTOSTART",
88 | "mhp:visibility": "VISIBLE_ALL",
89 | "mhp:serviceBound": "false",
90 | "mhp:priority": "1",
91 | "mhp:version": "01",
92 | "mhp:mhpVersion": {
93 | "mhp:profile": "0",
94 | "mhp:versionMajor": "1",
95 | "mhp:versionMinor": "3",
96 | "mhp:versionMicro": "1"
97 | }
98 | },
99 | "mhp:applicationTransport": {
100 | "@xsi:type": "mhp:HTTPTransportType",
101 | "mhp:URLBase": appUrlBase
102 | },
103 | "mhp:applicationLocation": appLocation
104 | }
105 | }
106 | }
107 | }
108 | };
109 | var launchReq = builder.create(mhp).end({ pretty: true});
110 | dialDevice.launchApp("HbbTV",launchReq, "text/plain", function (launchRes, err) {
111 | if(typeof launchRes != "undefined"){
112 | callback && callback(launchRes,err);
113 | }
114 | else if(err){
115 | callback && callback(null,err);
116 | }
117 | });
118 | }
119 | else {
120 | var err = new Error("mhp:applicationTransport->URLBase is mandatory and must be an valid URL");
121 | callback && callback(null,err);
122 | }
123 | };
124 |
125 | Object.defineProperty(this,"launchHbbTVApp", {
126 | get: function(){
127 | return launchHbbTVApp;
128 | }
129 | });
130 |
131 | Object.defineProperty(this,"getAppLaunchURL", {
132 | get: function(){
133 | return getAppLaunchURL;
134 | }
135 | });
136 |
137 | Object.defineProperty(this,"getApp2AppURL", {
138 | get: function(){
139 | return getApp2AppURL;
140 | }
141 | });
142 |
143 | Object.defineProperty(this,"getInterDevSyncURL", {
144 | get: function(){
145 | return getInterDevSyncURL;
146 | }
147 | });
148 |
149 | Object.defineProperty(this,"getUserAgent", {
150 | get: function(){
151 | return getUserAgent;
152 | }
153 | });
154 |
155 | Object.defineProperty(this,"getFriendlyName", {
156 | get: function(){
157 | return getFriendlyName;
158 | }
159 | });
160 |
161 | Object.defineProperty(this,"getInfo", {
162 | get: function(){
163 | return getInfo;
164 | }
165 | });
166 | };
167 |
168 | var HbbTVDialClient = function () {
169 | var dialClient = new dial.Client();
170 | var self = this;
171 | var terminals = {};
172 | dialClient.on("ready",function(){
173 | self.emit("ready");
174 | }).on("found",function(deviceDescriptionUrl, headers){
175 | dialClient.getDialDevice(deviceDescriptionUrl, function (dialDevice, err) {
176 | if(dialDevice){
177 | dialDevice.getAppInfo("HbbTV", function (appInfo, err) {
178 | if(appInfo){
179 | var terminal = new HbbTVTerminal(dialDevice, appInfo);
180 | terminals[deviceDescriptionUrl] = terminal;
181 | self.emit("found", terminal);
182 | }
183 | else if(err){
184 | // TODO check if this is an error or not
185 | //var error = new Error("Error on get HbbTV App Info or DIAL device is not a HbbTV Terminal", err.message);
186 | //self.emit("error", error);
187 | }
188 | });
189 | }
190 | else if(err){
191 | var error = new Error("Error on get device description from "+deviceDescriptionUrl, err.message);
192 | self.emit("error", error);
193 | }
194 | });
195 | }).on("disappear", function(deviceDescriptionUrl, headers){
196 | var terminal = terminals[deviceDescriptionUrl];
197 | delete terminals[deviceDescriptionUrl];
198 | self.emit("disappear",deviceDescriptionUrl, terminal);
199 | }).on("stop", function(){
200 | self.emit("stop");
201 | }).on("error", function (err) {
202 | self.emit("error",err);
203 | });
204 |
205 | var start = function () {
206 | dialClient.start();
207 | return this;
208 | };
209 |
210 | var refresh = function () {
211 | dialClient.refresh();
212 | return this;
213 | };
214 |
215 | var stop = function () {
216 | dialClient.stop();
217 | return this;
218 | };
219 |
220 | Object.defineProperty(this,"start", {
221 | get: function(){
222 | return start;
223 | }
224 | });
225 |
226 | Object.defineProperty(this,"refresh", {
227 | get: function(){
228 | return refresh;
229 | }
230 | });
231 |
232 | Object.defineProperty(this,"stop", {
233 | get: function(){
234 | return stop;
235 | }
236 | });
237 | };
238 |
239 | util.inherits(HbbTVDialClient, events.EventEmitter);
240 | module.exports = HbbTVDialClient;
--------------------------------------------------------------------------------
/lib/hbbtv-dial-server.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var dial = require("peer-dial");
22 | var util = require("util");
23 | var events = require("events");
24 | var opn = require("opn");
25 | var xml2js = require("xml2js");
26 | var HbbTVDialServer = function (expressApp, isCsLauncher) {
27 | var self = this;
28 | var MANUFACTURER = "Fraunhofer FOKUS";
29 | var MODEL_NAME = "HbbTV 2.0 Node.js Companion Screen Feature Emulator";
30 | var FRIENDLY_NAME = global.FRIENDLY_NAME; // May be null, in which case the hostname is used.
31 | var port = expressApp.get("port") || 80;
32 | var prefix = expressApp.get("dial-prefix") || "";
33 | var csManagerPrefix = expressApp.get("cs.manager-prefix") || "";
34 | var opnParams = expressApp.get("opn-params");
35 | isCsLauncher = (isCsLauncher == true);
36 | var apps = {
37 | "YouTube": {
38 | disabled: isCsLauncher,
39 | name: "YouTube",
40 | state: "stopped",
41 | allowStop: true,
42 | pid: null
43 | },
44 | "HbbTV": {
45 | disabled: isCsLauncher,
46 | name: "HbbTV",
47 | state: "running",
48 | allowStop: false,
49 | additionalData: {
50 | "hbbtv:X_HbbTV_App2AppURL":"",
51 | "hbbtv:X_HbbTV_InterDevSyncURL": "",
52 | "hbbtv:X_HbbTV_UserAgent": ""
53 | },
54 | namespaces: {
55 | "hbbtv": "urn:hbbtv:HbbTVCompanionScreen:2014"
56 | }
57 | },
58 | "Famium": {
59 | disabled: !isCsLauncher,
60 | name: "Famium",
61 | state: "running",
62 | allowStop: false,
63 | additionalData: {
64 | "famium:X_FAMIUM_CS_OS_ID":"de.fhg.fokus.famium.applauncher/0.0.1"
65 | },
66 | namespaces: {
67 | "famium": "http://famium.fokus.fraunhofer.de"
68 | }
69 | }
70 | };
71 |
72 | var openUrl = function (url) {
73 | try{
74 | opn(url, opnParams);
75 | }
76 | catch(err){
77 | console.error("Error on open URL", err.message);
78 | }
79 | };
80 |
81 | var launchApp = function (app, launchData, callback) {
82 | var self = this;
83 | if(app.name == "YouTube"){
84 | app.pid = "run";
85 | app.state = "starting";
86 | openUrl("http://www.youtube.com/tv?"+launchData);
87 | app.state = "running";
88 | callback && callback(app.pid);
89 | }
90 | else if(app.name == "HbbTV"){
91 | xml2js.parseString(launchData, {
92 | trim: true,
93 | explicitArray: false,
94 | mergeAttrs: true,
95 | explicitRoot: false,
96 | tagNameProcessors: [function(tagName){
97 | tagName = tagName.substr(tagName.indexOf(":")+1);
98 | return tagName;
99 | }],
100 | attrNameProcessors: [function(attrName){
101 | attrName = attrName.substr(attrName.indexOf(":")+1);
102 | return attrName;
103 | }]
104 | },function (err, launchData) {
105 | if(err){
106 | callback && callback(null,err);
107 | }
108 | else {
109 | try {
110 | var appUrlBase = launchData.ApplicationDiscovery.ApplicationList.Application.applicationTransport.URLBase || "";
111 | var appLocation = launchData.ApplicationDiscovery.ApplicationList.Application.applicationLocation || "";
112 | var url = appUrlBase && (appUrlBase+appLocation) || null;
113 | if(url){
114 | var csManagerParameters = "port="+port+"&hostname="+self.hostname;
115 | openUrl(url+"#"+csManagerParameters);
116 | app.state = "running";
117 | callback && callback(app.pid);
118 | }
119 | else {
120 | callback && callback(null, new Error("URLBase element in the XML MHP of the DIAL Launch Request is missing or empty"));
121 | }
122 | }
123 | catch (err){
124 | callback && callback(null, err);
125 | }
126 | }
127 | });
128 | }
129 | else if(app.name == "Famium"){
130 | try{
131 | launchData = JSON.parse(launchData);
132 | var url = null;
133 | //for(var i in launchData.launch){
134 | for(var i=0; i.
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var HbbTVCsManager = require("./hbbtv-cs-manager.js");
22 | var util = require("util");
23 |
24 | var HbbTVTerminalManager = function (httpServer) {
25 | var isCs = true;
26 | HbbTVCsManager.call(this,httpServer,isCs);
27 | };
28 |
29 | util.inherits(HbbTVTerminalManager, HbbTVCsManager);
30 | module.exports = HbbTVTerminalManager;
--------------------------------------------------------------------------------
/lib/hbbtv.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var WebSocket = require("ws");
22 | var HbbTVApp2AppServer = require("./hbbtv-app2app-server.js");
23 | var HbbTVDialServer = require("./hbbtv-dial-server.js");
24 | var HbbTVDialClient = require("./hbbtv-dial-client.js");
25 | var CsLauncherDialServer = require("./cs-launcher-dial-server.js");
26 | var CsLauncherDialClient = require("./cs-launcher-dial-client.js");
27 | var HbbTVCsManager = require("./hbbtv-cs-manager.js");
28 | var HbbTVTerminalManager = require("./hbbtv-terminal-manager.js");
29 |
30 | module.exports.HbbTVApp2AppServer = HbbTVApp2AppServer;
31 | module.exports.HbbTVDialServer = HbbTVDialServer;
32 | module.exports.HbbTVDialClient = HbbTVDialClient;
33 | module.exports.CsLauncherDialServer = CsLauncherDialServer;
34 | module.exports.CsLauncherDialClient = CsLauncherDialClient;
35 | module.exports.HbbTVCsManager = HbbTVCsManager;
36 | module.exports.HbbTVTerminalManager = HbbTVTerminalManager;
37 | module.exports.WebSocket = WebSocket;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hbbtv",
3 | "description": "Nodejs implementation of the HbbTV Companion Screen",
4 | "version": "0.0.11",
5 | "author": {
6 | "name": "Louay Bassbouss",
7 | "email": "louay.bassbouss@fokus.fraunhofer.de"
8 | },
9 | "homepage": "http://www.fokus.fraunhofer.de/fame",
10 | "license": "LGPL-3.0",
11 | "preferGlobal": true,
12 | "keywords": ["ssdp", "nsd", "discovery", "launch", "dial","hbbtv","hbbtv 2.0","hbbtv 2.0 cs","cs", "ws", "websocket", "app2app"],
13 | "main": "index",
14 | "dependencies" : {
15 | "peer-dial": "0.0.8",
16 | "node-uuid": "1.4.1",
17 | "ws": "0.7.2",
18 | "express": "4.20.0",
19 | "opn": "2.0.0",
20 | "xml2js": "0.5.0",
21 | "xmlbuilder": "2.6.4",
22 | "commander": "2.8.1"
23 | },
24 | "bin": {
25 | "hbbtv": "bin/index.js"
26 | },
27 | "repository": "https://github.com/fraunhoferfokus/node-hbbtv.git",
28 | "readmeFilename": "Readme.md",
29 | "_id": "hbbtv@0.0.11",
30 | "_from": "hbbtv@*"
31 | }
32 |
--------------------------------------------------------------------------------
/test/app2app-local-client.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by lba on 16/06/15.
3 | */
4 |
5 | (function(){
6 | // this example code works in Node.js and Browser.
7 | if(typeof window == "undefined"){
8 | // we are in Node.js. import required modules
9 | var hbbtv = require("../index.js");
10 | WebSocket = hbbtv.WebSocket;
11 | }
12 | var run = function(){
13 | var app2appLocalBaseUrl = "ws://localhost:8080/local/" ;
14 | var appEndpoint = "org.mychannel.myapp";
15 | var createConnection = function (index) {
16 | var ws = new WebSocket(app2appLocalBaseUrl + appEndpoint);
17 | ws.binaryType = "arraybuffer";
18 | ws.onopen = function(evt) {
19 | console.log("Connection ",index," waiting ...");
20 | };
21 | ws.onclose = function(evt) {
22 | console.log("Connection ",index," closed.");
23 | };
24 | ws.onerror = function (evt) {
25 | console.log("Connection error.");
26 | };
27 | ws.onmessage = function(evt) {
28 | if (evt.data == "pairingcompleted") {
29 | console.log("connection ",index," paired");
30 | ws.onmessage = function(evt) {
31 | if(typeof evt.data == "string"){
32 | console.log( "Received Message: " + evt.data);
33 | }
34 | else {
35 | var data = typeof Buffer != "undefined"?new Buffer(evt.data): new Int8Array(evt.data);
36 | console.log("Received Binary Message of " + data.length + " bytes", data);
37 | }
38 | };
39 | ws.send("Hello from HbbTV App: "+index);
40 | createConnection(index+1);
41 | } else {
42 | console.log("Unexpected message received from terminal.");
43 | ws.close();
44 | }
45 | };
46 | };
47 | createConnection(0);
48 | };
49 | run();
50 | })();
--------------------------------------------------------------------------------
/test/app2app-remote-client.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by lba on 16/06/15.
3 | */
4 |
5 | (function(){
6 | // this example code works in Node.js and Browser.
7 | if(typeof window == "undefined"){
8 | // we are in Node.js. import required modules
9 | var hbbtv = require("../index.js");
10 | WebSocket = hbbtv.WebSocket;
11 | }
12 | var run = function(){
13 | var app2appRemoteBaseUrl = "ws://localhost:8080/remote/" ;
14 | var appEndpoint = "org.mychannel.myapp";
15 | var ws = new WebSocket(app2appRemoteBaseUrl + appEndpoint);
16 | ws.binaryType = "arraybuffer";
17 | ws.onopen = function(evt) {
18 | console.log("Connection waiting ...");
19 | };
20 | ws.onclose = function(evt) {
21 | console.log("Connection closed.");
22 | };
23 | ws.onerror = function (evt) {
24 | console.log("Connection error.");
25 | };
26 | ws.onmessage = function(evt) {
27 | if (evt.data == "pairingcompleted") {
28 | console.log("connection paired");
29 | ws.onmessage = function(evt) {
30 | console.log( "Received Message: " + evt.data);
31 | };
32 | var data = "Hello from Companion Screen";
33 | ws.send(data);
34 | var array = [0,1,2,3,4,5,6,7,8,9];
35 | data = typeof Buffer != "undefined"?new Buffer(array): new Int8Array(array).buffer;
36 | ws.send(data);
37 | } else {
38 | console.log("Unexpected message received from terminal.");
39 | ws.close();
40 | }
41 | };
42 | }
43 | run();
44 | })();
45 |
46 |
--------------------------------------------------------------------------------
/test/hbbtv-nodejs-client.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | *
3 | * Copyright (c) 2015 Louay Bassbouss, Fraunhofer FOKUS, All rights reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 3.0 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library. If not, see .
17 | *
18 | * AUTHORS: Louay Bassbouss (louay.bassbouss@fokus.fraunhofer.de)
19 | *
20 | ******************************************************************************/
21 | var hbbtv = require("../index.js");
22 | var HbbTVDialClient = hbbtv.HbbTVDialClient;
23 | var WebSocket = hbbtv.WebSocket;
24 |
25 | var hbbTVDialClient = new HbbTVDialClient().on("ready", function () {
26 | console.log("HbbTV DIAL Client is ready");
27 | }).on("stop", function () {
28 | console.log("HbbTV DIAL Client is stopped");
29 | }).on("found", function (terminal) {
30 | console.log("HbbTV Terminal ", terminal.getFriendlyName()," (", terminal.getAppLaunchURL(), ") found");
31 | var channel = (""+Math.random()).substr(2,16);
32 | terminal.launchHbbTVApp({
33 | "appUrlBase": "http://fraunhoferfokus.github.io/node-hbbtv/www/hbbtv-app.html",
34 | "appLocation": "?channel="+channel
35 | }, function (launchRes,err) {
36 | if(err){
37 | console.error("Error on launch HbbTV App", err);
38 | }
39 | else {
40 | console.log("HbbTV App launched successfully: ",launchRes || "");
41 | createConnection(terminal, channel);
42 | }
43 | });
44 | }).on("error", function (err) {
45 | console.error(err);
46 | });
47 |
48 | var createConnection = function (terminal, channel) {
49 | var app2appRemoteBaseUrl = terminal.getApp2AppURL();
50 | var ws = new WebSocket(app2appRemoteBaseUrl + channel);
51 | ws.binaryType = "arraybuffer";
52 | ws.onopen = function(evt) {
53 | console.log("Connection waiting ...");
54 | };
55 | ws.onclose = function(evt) {
56 | console.log("Connection closed.");
57 | };
58 | ws.onerror = function (evt) {
59 | console.log("Connection error.");
60 | };
61 | ws.onmessage = function(evt) {
62 | if (evt.data == "pairingcompleted") {
63 | console.log("pairing complete");
64 | ws.onmessage = function(evt) {
65 | console.log( "Received Message: " + evt.data);
66 | };
67 | var data = "Hello from Companion Screen";
68 | ws.send(data);
69 | var array = [0,1,2,3,4,5,6,7,8,9];
70 | data = typeof Buffer != "undefined"?new Buffer(array): new Int8Array(array).buffer;
71 | ws.send(data);
72 | } else {
73 | console.log("Unexpected message received from terminal.");
74 | ws.close();
75 | }
76 | };
77 | };
78 |
79 | hbbTVDialClient.start();
--------------------------------------------------------------------------------
/www/cs-app.html:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
27 | Companion Screen App
28 |
29 |
30 |
31 |
32 |