HTML Development
Node.js
21min
our customers often need to communicate between applications on a brightsign player, or between a brightsign player and the outside world this can be done using various protocols http, serial, and udp are the most popular you can write applications in either brightscript or javascript to create this functionality if you choose to write your application in javascript, you will need node js® to implement features such as hosting a web server in javascript brightsign makes a node js endpoint available so that our partners can use node js modules and features brightsign node js implementation brightsign players support the node js runtime environment, which runs on the same v8 javascript engine used by chromium the node js® and chromium instances share a single javascript execution context, so javascript applications can access both node js modules and dom objects at the same time brightsign firmware pushes node js events to the chromium event loop, ensuring that javascript applications receive node js and dom events seamlessly the brightsign node js implementation is based on the nw\ js https //github com/nwjs/nw\ js and electron https //github com/electron/electron projects and shares many characteristics with them whereas electron uses a javascript file as the entry point (i e the javascript file creates a webview, which also has access to the node js runtime), nw\ js and brightsign use an html file as the entry point on a brightsign player, brightscript creates a node js enabled rohtmlwidget instance; the initial url, which is passed when rohtmlwidget is initialized, acts as the entry point for node js applications like nw\ js and electron, brightsign does not use sandboxing instead, it launches the render process with a node js user and storage group, which has write permissions for local storage and read permissions for the entire file system it also can access networking interfaces and use privileged ports the integrated node js implementation in os 8 2 x and os 8 3 x is based on node v10 for further documentation and usage information, consult the node js 10 0 0 api documentation https //nodejs org/dist/v10 0 0/docs/api/ node js is not enabled for iframes or web workers enabling node js node js object functionality is available in brightauthor\ connected when users specify node js items in presentation settings docid\ a6ali6u szxhuansk6t3 node js objects are not available in brightauthor node js is enabled for individual rohtmlwidget instances by including the nodejs enabled\ true entry in the rohtmlwidget docid\ xljq5 yhdma2ssmpzimtk object example r=createobject("rorectangle", 0,0,1920,1080) is = { 	port 3000 } config = { 	nodejs enabled true 	inspector server is 	brightsign js objects enabled true 	url "file ///sd /nodehello html" } h=createobject("rohtmlwidget", r, config) h show() we do not recommend loading arbitrary websites with node js enabled some javascript libraries assume that node js is running on an instance with server side capabilities, and they will attempt to load dependencies, causing playback to fail if you are using a brightauthor plugin to enable node js, you will need to set other desired parameters in the plugin, rather than with an html5 state for example, if you want to enable the mouse cursor, you will need to set mouse enabled\ true during the rohtmlwidget initialization, rather than checking the box in the html5 state cross domain security chromium has default security measures for preventing cross site scripting attacks if the url for the rohtmlwidget instance is a remote domain, javascript applications from that domain cannot make http requests to other domains; on the other hand, if the url points to local storage, requests to other, remote domains are acceptable if you want to reference other domains in remote applications, set the websecurity parameter to false when initalizing the rohtmlwidget , as shown below example r=createobject("rorectangle", 0,0,1920,1080) is = { 	port 3000 } config = { 	nodejs enabled true 	inspector server is 	brightsign js objects enabled true 	url "http //www mysitehere com" 	security params {websecurity false} } h=createobject("rohtmlwidget", r, config) h show() web storage if you want to use javascript storage applications, you will need to specify a storage path and storage quota when initializaing the rohtmlwidget example r=createobject("rorectangle", 0,0,1920,1080) is = { 	port 3000 } config = { 	nodejs enabled true 	inspector server is 	brightsign js objects enabled true 	url "file ///sd /nodehello html" 	storage path "sd " 	storage quota 1073741824 } h=createobject("rohtmlwidget", r, config) h show() jquery jquery® requires a workaround to operate correctly with node js (see this page https //stackoverflow\ com/questions/4299363/how to use jquery selectors in node js for an example) this workaround requires modifying the content, so if you don't have control over the webpage enabling node in your html widget, this can cause an intractable problem you should only enable node js if you are planning to use it (for example with our javascript apis docid\ o2uiynvkbsyd1qxcvhvcn ) see also html best practices docid\ gxctvnw8g46evdxookuku node serialport the brightsign player provides javascript serial port bindings for the node serialport package these bindings can be used using with the @brightsign/serialport api const serialport = require('@serialport/stream'); const brightsignbinding = require('@brightsign/serialport'); serialport binding = brightsignbinding; also see our reference implementation https //github com/brightsign/bs node serialport on github reloading node js enabled web applications any customer application that uses @brightsign objects, and some of the "bs" objects, will throw a javascript exception when reloaded in brightsignos 8 0 to 8 4 (even though it may have worked in os 7 x and earlier) due to limitations with native modules in node 10 this problem will be fixed in os 8 5 and above, which ships with node 14 x you can also disable node js (and @brightsign objects) if you don’t need it packaging and delivering node js applications if you are using electron/chromium 110 or a later version, brightsign no longer supports any brightscript/javascript objects in iframes for security reasons iframes requests should be sent to parent https //nam04 safelinks protection outlook com/?url=https%3a%2f%2fdeveloper mozilla org%2fen us%2fdocs%2fweb%2fapi%2fwindow%2fparent\&data=05%7c02%7csmulqueen%40brightsign biz%7cc0b4df4b1a374212f14308dc95fa4ac2%7c8fbcdf641ab847cebdc743e23b04fb3c%7c0%7c0%7c638550149459230214%7cunknown%7ctwfpbgzsb3d8eyjwijoimc4wljawmdailcjqijoiv2lumziilcjbtii6ik1hawwilcjxvci6mn0%3d%7c0%7c%7c%7c\&sdata=%2bbc0offac7laewddoehvxi7wjyxdfmvlphpv6ynkl1g%3d\&reserved=0 and then the parent page should call brightsign/javascript objects to deploy your node js application to a brightsign player, run "npm install" on your computer this will create the node modules directory copy this directory to the sd card along with the rest of the application when initialized, the brightsign node js implementation seeks to the node modules directory relative to the loaded html file like a standard node js application, it then loads all modules contained in the node modules directory the majority of node js modules contain javascript code only however, some modules contain binary code when a module containing binary parts is installed using "npm install", the binary parts are compiled for the local platform (usually intel x64), and this code will not run on a brightsign player currently, the brightsign node js implementation is limited to javascript code only webpack the node modules directory associated with a node js application may contain hundreds or thousands of unnecessary files the webpack https //webpack js org/ ® bundler allows you to reduce the node modules directory to a manageable size to use webpack®, you will need to place your node js entry point function in a separate file (e g "index js"), rather than as inline html this file will contain the references to other javascript files and node js modules example index js var myutils = require(' /utilities'); // my utilities js var moment = require('moment'); // a node module function main() { myutils foo(); moment now(); // } the javascript file containing the node js entry point can then be referenced in the html file example html \<script src=' /index js'>\</script> to use webpack®, attach main() to the window object so that it can be found from the html file var myutils = require(' /utilities'); // my utilities js var moment = require('moment'); // a node module function main() { myutils foo(); moment now(); // } window\ main = main; change the html file so that it points to the bundled javascript and to window\ main() \<script src=' /bundle js'>\</script> \<body onload="window\ main()"> to build your bundle, run the following npm steps on your computer npm i d webpack webpack cli npx webpack mode production now you can publish the index html and bundle js files; there's no need to publish the node modules directory see the sample webpack® configuration below for more information https //archbee doc uploads s3 amazonaws com/0prk6so2dy9ldu77jb8d1/llocj1qfrweqkablldsxf webpackconfig js device storage paths to load node js modules and read/write files, you must first define the root directory of the device storage the following are common root directories microsd "storage/sd/" ssd "storage/ssd/" usb "storage/usb1/" we recommend using the process chdir() call at the beginning of the script to change the process path example var process = require("process"); process chdir("/storage/sd"); alternatively, if you have modules located on multiple storage drives, you can append multiple search paths to a module example module paths push("/storage/sd/") module paths push("/storage/ssd/") module paths push("/storage/usb1/") debugging applications when node js modules are enabled, they become visible from the debugging webpages docid 4qlk1krr1cnx7xypwxry5 , allowing you to debug applications the console log works like a normal web application output is redirected to both stderr and the remote inspector downloading large files if your application uses the xmlhttprequest object to download a large file (100 200mb, depending on the player model), the player will run out of memory and the download operation will fail the xmlhttprequest object first downloads the whole file into memory, then creates a blob object of equal size, so memory requirements for a download are effectively double that of the file size for large file downloads, we recommend using the fetch api https //developer mozilla org/en us/docs/web/api/fetch api , which has callbacks that are fired when fragments are downloaded data can be appended to the disk as it arrives, so the player won't run out of memory, no matter the file size the "download test" html/javascript example below uses the fetch api and the node js file service module to download a file in fragments https //archbee doc uploads s3 amazonaws com/0prk6so2dy9ldu77jb8d1/1hcizt5x 06 ub6zqmgsd download test zip this example is specific to brightsign players and requires node js runtime, enabled by use of the rohtmlwidget nodejs enabled flag, to write files to disk node js examples github contains a node js starter project https //github com/brightsign/node js starter project this project was originally created for brightauthor but can also be used with brightauthor\ connected another example is the script below, which initializes an http server on the brightsign player at port 8000 when a client (for example, a desktop browser) connects to the server, it will send the model number and boot version of the player to the client the script also displays the ip address of the connected client on the screen attached to the player example \<html> \<script> function displaymessage() { // load the http module to create an http server var http = require('http'); // configure our http server to respond with hello world to all requests var server = http createserver(function (request, response) { var device info = new bsdeviceinfo(); response writehead(200, {"content type" "text/plain"}); response end("device information \n" + device info model + "\n" + device info bootversion + "\n"); var ip = request connection remoteaddress; document getelementbyid("ip") innerhtml+="server responded to "+ ip + "\<br>"; console log("server responded to request from " + ip); }); // listen on port 8000, ip defaults to 127 0 0 1 server listen(8000); // display it on brightsign browser var os = require('os'); var interfaces = os networkinterfaces(); var addresses = \[]; for (var k in interfaces) { for (var k2 in interfaces\[k]) { var address = interfaces\[k]\[k2]; if (address family === 'ipv4' && !address internal) { addresses push(address address); } } } var message = "server running at " + addresses\[0] + " 8000\<br>"; document getelementbyid("ip") innerhtml+= message; // print message on console console log(message); } \</script> \<body style="background color\ red" onload="displaymessage()"> \<div id = "ip" style="font size 60px; text align\ center;"> \</div> \</body> \</html> built in modules, such as "os" and "http", can be initialized using the require() method if the nodejs enabled\ true entry is not included when initializing the rohtmlwidget object (as shown above), the require() method will not be available