Functionality of JSScripting vs. node.js

Hi,

this week I started playing around with the powerful JSscripting 3.2 engine, but ran into a few issues using npm modules.

I tried using a script that runs fine with nodejs and makes use of libraries like Jimp, gifwrap and ws (WebSockets).

However, after installing the libraries in the node_modules directory, I soon ran into two types of problems:

  • GraalVM seems to love all js files below this directory - including those integrated into the libraries for testing purposes etc.
[ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/node_modules/process/test.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'assert'
[ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/node_modules/xml2js/lib/builder.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: './defaults'
[ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab/automation/js/node_modules/xtend/test.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'tape'

=> Do I understand correctly that this behavior is part of [jsscripting] JS script engine no longer watches node_modules for scripts by jpg0 · Pull Request #11830 · openhab/openhab-addons · GitHub and should be fixed when I install a nightly build?

  • GraalVM does not provide all built-in functionality that is included with nodejs.
[ERROR] [b.automation.script.javascript.stack] - Failed to execute script: org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'assert'
[ERROR] [b.automation.script.javascript.stack] - Failed to execute script: org.graalvm.polyglot.PolyglotException: TypeError: (intermediate value).nextTick is not a function
[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ede0555c07' failed: org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'events'
[ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'https'

Is there anything I can do to get this functionality?

Not tested yet, but I for sure know that some of the libs I use make extended use of Promises. Will these work, or will this become the next issue, given that GraalVM is single-threaded?

@rlkoshak Thanks for your great work and tutorials!

My understanding is to get full node support one has to run an instance of Node.js along side of openHAB and start up GraalVM with a different set of flags. That’s not really something we know how to package up and distribute as part of OH and I know of no one who has successfully done it yet. You can find details at Node.js Runtime.

I can’t answer the first question.

Not at this time and I don’t know if ever. See Multithreading. In particular:

  1. An arbitrary number of JavaScript Contexts can be created, but they should be used by one thread at a time.
  2. Concurrent access to JavaScript objects is not allowed: any JavaScript object cannot be accessed by more than one thread at a time.
  3. Concurrent access to Java objects is allowed: any Java object can be accessed by any Java or JavaScript thread, concurrently.

Because of the way that rules are run, attempting to do anything with threads results in a “single threaded only” exception because it causes concurrent access to JS objects (namely the script). And there is no internal loop driving things like in Node so if you set a promise the script just exits. There is nothing waking it up to see if the promise has been met.

All of these issues are known and being explored but there is no timeline for when/if they can be addressed.

1 Like

Hi Rich,

thanks for your valuable input. I decided to use node.js separately from OpenHAB, additionally run node-RED and have those two communicate via Items. By this, functionality that requires libraries can be placed in and administered by Node-RED, and everything that belongs to OpenHAB will happen in OpenHAB.

Thanks again! The new JS engine makes OH much more powerful!

I´m interested in this solution. How did you manage a separate node.js instance and communication with OpenHAB?
Currently, I have a linux server with current OpenHAB and use node.js with JavaScript classes as part of my own programming. Triggered via a JSRule and I read/write OpenHAB items.
Is it appropriate to set up another linux server with node.js, let my programming run there and “attach” it somehow to OpenHAB?

OH has a REST API and websocket and SSE stream external services can used to interact with openHAB. You’ll have to implement code to interact with this API. HAPApp used this approach for Python 3.

I simply installed NodeRed on the very same machine as OpenHAB. Next I installed the OpenHAB addons to NodeRed. I am using specific items for communication between flows in NodeRed and OpenHAB.

For example, this flow accepts either filenames with GIF files that have to be displayed on a display or a STOP command. After the GIF file has been stopped, it returns that state via another item.

The three parallel nodes contain JavaScript programs that process GIF files, split them into frames, create bitmaps from them and transmit them via websockets to the displays.

There are several other flows that interact with databases etc.