Closed LukasA83 closed 3 years ago
So you've done everything right, however I don't yet have ohj
fully working with OH3 yet.
So I would suggest to either:
ohj
updated, then you can use the library as you are doing hereohj
library. This would require using the OH scriptextensions directly: let simpleRule = require("@runtime/RuleSimple").SimpleRule; ...
Either way, I'll update this once ohj
is working (shouldn't be too long, depends on my time during this period!).
Right now I'm still using the javascript helpers provided for OH 2.5 with own Utils and same updates for OH3. Will it work to keep the set-up, maybe with minor adaptions to GraalJS? That would allow me a staggered migration ;-)
Additional question: Going forward will I need to install npm to the Openhab docker image? That feels unhandy in terms of updates.
npm shouldn't be required in the docker image. It only downloads and places the JS files, so can do it from the host. It's not needed to run the downloaded JS.
As for migration; this is possible, but not as simple as you may expect (it's what I originally did, to try to keep compatibility, but ultimately abandoned). The reason is the global namespacing in the 2.5 helpers; almost all variables in the 2.5 helpers are dropped into the global namespace, whereas the pattern I use for 3.0 is the same as standard module-based JS, where they are put into a specific namespace. So for example:
With namespacing:
let mythings = require('mythings'); //or import scriptExtensions, same pattern
let doorItem = mythings.door;
Without namespacing:
load("../somecrazypath/mythings.js"); //or scriptExtension.importPreset("mythings");
let doorItem = door; //this was just retrieved from the global namespace
I tried to ease migration by explicitly copying namespaced properties into the global namespace to try to emulate the 2.5 approach. This mostly worked, but there were unexpected clashes and overrides all the time that were frustrating. Saying this, if your usage of the 2.5 helpers is simple, it could certainly work. At the very least - examples of how you migrate could certainly help others.
I have published a new version of ohj
(3.0.0, to match the OH version that it is targeting). Whilst I have not tested it extensively, it looks to be working fine with OH3.
Today I tried again. Following steps I did:
ohj package.json indicates right version:
{
"dependencies": {
"ohj": "^3.0.0"
}
}
Now I get this error:
During startup:
12:29:11.409 [INFO ] [org.openhab.ui.internal.UIService ] - Started UI on port 50880, 12:29:10.531 [INFO ] [ab.core.service.AbstractWatchService] - Loading script '/openhab/conf/automation/jsr223/javascript/personal/fritzbox.js', 12:29:10.526 [DEBUG] [enhab.core.service.StartLevelService] - Reached start level 20, 12:29:15.535 [INFO ] [e.automation.internal.RuleEngineImpl] - Rule engine started., 12:29:15.532 [DEBUG] [enhab.core.service.StartLevelService] - Reached start level 40, 12:29:15.529 [DEBUG] [enhab.core.service.StartLevelService] - Reached start level 30, 12:29:16.313 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/openhab/conf/automation/jsr223/javascript/personal/fritzbox.js': <eval>:65:51 Expected an operand but found ), when(item("Test_Item_Switch").changed()).then(() => { logWarn("testwarn"); });, 12:29:17.450 [WARN ] [ty.util.ssl.SslContextFactory.config] - Trusting all certificates configured for Client@7a6c3c46[provider=null,keyStore=null,trustStore=null], ^ in <eval> at line number 65 at column number 51
When changing the rule after startup:
`2:30:15.585 [INFO ] [ab.core.service.AbstractWatchService] - Loading script '/openhab/conf/automation/jsr223/javascript/personal/fritzbox.js'
12:30:19.866 [WARN ] [.internal.OpenhabGraalJSScriptEngine] - Failed to retrieve script script dependency listener from engine bindings. Script dependency tracking will be disabled.
12:30:20.509 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'ohj'
at <js>.:program(<eval>:41) ~[?:?]
at org.graalvm.polyglot.Context.eval(Context.java:345) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:379) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:343) ~[?:?]
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249) ~[java.scripting:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:78) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:78) [bundleFile:?]
at org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl.loadScript(ScriptEngineManagerImpl.java:170) [bundleFile:?]
at org.openhab.core.automation.module.script.rulesupport.internal.loader.ScriptFileWatcher.importFile(ScriptFileWatcher.java:191) [bundleFile:?]
at org.openhab.core.automation.module.script.rulesupport.internal.loader.ScriptFileWatcher.processWatchEvent(ScriptFileWatcher.java:157) [bundleFile:?]
at org.openhab.core.service.WatchQueueReader.lambda$3(WatchQueueReader.java:322) [bundleFile:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:834) [?:?]
12:30:20.537 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/openhab/conf/automation/jsr223/javascript/personal/fritzbox.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'ohj'`
I created another js file with some dummy set-up which works, so it seems I'm still struggling with the npm ohj package. Any idea what is going wrong? Dummy script, that works:
const GENERATED_RULE_ITEM_TAG = "GENERATED_RULE_ITEM";
const ModuleBuilder = Java.type("org.openhab.core.automation.util.ModuleBuilder");
const Configuration = Java.type("org.openhab.core.config.core.Configuration");
const LOGGER_PREFIX = "script.js";
let logger = Java.type("org.slf4j.LoggerFactory").getLogger(LOGGER_PREFIX);
//let RuleManager = osgi.getService("org.openhab.core.automation.RuleManager");
const { automationManager } = require('@runtime/RuleSupport');
/**
* Creates a trigger. Internal function, instead use predefined trigger types.
*
* @memberof triggers
* @private
* @param {String} typeString the type of trigger to create
* @param {String} [name] the name of the trigger
* @param {Configuration} config the trigger configuration
*/
let createTrigger = function(typeString, name, config) {
return ModuleBuilder.createTrigger()
.withId(name)
.withTypeUID(typeString)
.withConfiguration(new Configuration(config))
.build();
}
/**
* Creates a rule. The rule will be created and immediately available.
*
* @example
* import { rules, triggers } = require('ohj');
*
* rules.JSRule({
* name: "my_new_rule",
* description": "this rule swizzles the swallows",
* triggers: triggers.GenericCronTrigger("0 30 16 * * ? *"),
* execute: triggerConfig => { //do stuff }
* });
*
* @memberOf rules
* @param {Object} ruleConfig The rule config describing the rule
* @param {String} ruleConfig.name the name of the rule
* @param {String} ruleConfig.description a description of the rule
* @param {*} ruleConfig.execute callback that will be called when the rule fires
* @returns {HostRule} the created rule
*/
let JSRule = function (ruleConfig) {
let ruid = ruleConfig.id || ruleConfig.name.replace(/[^\w]/g, "-") + "-";
let ruTemplateid = ruleConfig.name.replace(/[^\w]/g, "-") + "-";
logger.info("Adding rule: {}", ruleConfig.name ? ruleConfig.name : ruid);
let SimpleRule = Java.extend(Java.type('org.openhab.core.automation.module.script.rulesupport.shared.simple.SimpleRule'));
let doExecute = function (module, input) {
try {
return ruleConfig.execute(input);
} catch (error) {
logger.error(`Failed to execute rule ${ruid}: ${error}: ${error.stack}`);
throw error;
}
};
var rule = new SimpleRule({
execute: doExecute,
getUID: () => ruid
});
var triggers = ruleConfig.triggers ? ruleConfig.triggers : ruleConfig.getEventTrigger();
rule.setTemplateUID(ruTemplateid);
if (ruleConfig.description) {
rule.setDescription(ruleConfig.description);
}
if (ruleConfig.name) {
rule.setName(ruleConfig.name);
}
//Register rule here
if (triggers && triggers.length > 0) {
rule.setTriggers(triggers);
rule = registerRule(rule);
}
return rule;
};
let currentProvider = automationManager;
let registerRule = function(rule) {
return currentProvider.addRule(rule);
}
let testRule = JSRule({
name: "new rule the old way",
triggers: [
createTrigger("timer.GenericCronTrigger","cron-trigger",{
"cronExpression": "0/30 * * * * ? *"
})
],
description: "bla",
execute: triggerConfig => {
logger.warn("new rule trigger");
}
});
Ok I think I found one issue. In the readme you refer to install the npm package to the community folder, but it seems it has to be in the personal folder. Now I'm getting this error:
23:21:37.916 [WARN ] [script.js.osgi ] - Failed to get service org.openhab.core.items.MetadataRegistry: [object Error] [osgi at source <unknown>, line 53]
23:21:37.931 [WARN ] [script.js.osgi ] - Failed to get service org.eclipse.smarthome.core.items.MetadataRegistry: [object Error] [osgi at source <unknown>, line 53]
23:21:37.947 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: Error: Failed to get any services of type(s): org.openhab.core.items.MetadataRegistry,org.eclipse.smarthome.core.items.MetadataRegistry
at <js>.getService(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/osgi.js:71) ~[?:?]
at <js>.:anonymous(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/metadata/metadata.js:13) ~[?:?]
at <js>.:anonymous(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/items/managed.js:6) ~[?:?]
at <js>.:anonymous(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/items/items.js:8) ~[?:?]
at <js>.:anonymous(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/fluent/fluent.js:9) ~[?:?]
at <js>.get fluent(/openhab/conf/automation/lib/javascript/personal/node_modules/ohj/index.js:12) ~[?:?]
at <js>.:program(<eval>:41) ~[?:?]
at org.graalvm.polyglot.Context.eval(Context.java:345) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:379) ~[?:?]
at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:343) ~[?:?]
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249) ~[java.scripting:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:78) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[bundleFile:?]
at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:78) [bundleFile:?]
at org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl.loadScript(ScriptEngineManagerImpl.java:170) [bundleFile:?]
at org.openhab.core.automation.module.script.rulesupport.internal.loader.ScriptFileWatcher.importFile(ScriptFileWatcher.java:191) [bundleFile:?]
at org.openhab.core.automation.module.script.rulesupport.internal.loader.ScriptFileWatcher.processWatchEvent(ScriptFileWatcher.java:157) [bundleFile:?]
at org.openhab.core.service.WatchQueueReader.lambda$3(WatchQueueReader.java:322) [bundleFile:?]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.lang.Thread.run(Thread.java:834) [?:?]
23:21:37.953 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/openhab/conf/automation/jsr223/javascript/personal/fritzbox.js': org.graalvm.polyglot.PolyglotException: Error: Failed to get any services of type(s): org.openhab.core.items.MetadataRegistry,org.eclipse.smarthome.core.items.MetadataRegistry
Sorry that you're having so many issues!
I can see a few causes here:
personal
folder, not community
. NodeJS only allows a single library folder, and so does GraalJS.ohj
) into ohj-support: https://github.com/jpg0/ohj-support/. I'll upload a build of this...Also: what version of ohj
do you have installed? You should be able to see this in the package.json
file in the ohj
directory. You want 3.0.0.
I ask this because it's failing to load MetadataRegistry
, although I am not seeing that error.
Here's a build of ohj-support:
I backtraced the error to the osgi.js. the bundleContext seems to be undefined.
Oh, and great news that the dummy script works - that signifies that the base JS + modules are working (plus I see it has ES6+ features in there like const
, which would fail with the current JS engine). So it's just ohj
which is the problem here.
I've added the support addon, still bundleContext seems to be undefined in osgi.js. Any idea?
I got it to work with changing the function "lookupService" in osgi,js like this (quick hack...):
let lookupService = function (classOrName) {
var bc = bundleContext;
if(bundleContext === undefined) {
log.warn("bundleContext is undefined");
var FrameworkUtil = Java.type("org.osgi.framework.FrameworkUtil");
var _bundle = FrameworkUtil.getBundle(scriptExtension.class);
bc = (_bundle !== null) ? _bundle.getBundleContext() : null;
}
if (bc !== null) {
var classname = (typeof classOrName === "object") ? classOrName.getName() : classOrName;
var ref = bc.getServiceReference(classname);
return (ref !== null) ? bc.getService(ref) : null;
}
}
Great! Thanks for letting me know. It looks like you are not resolving require('@runtime/osgi').bundleContext
for some reason (it's supplied in ohj-support: https://github.com/jpg0/ohj-support/blob/master/src/main/java/org/openhab/automation/module/script/extension/OSGiScriptExtensionProvider.java).
Either way, I wouldn't worry about it if I were you - your hack should work fine and I'll try to figure out why the standard version is not resolving. ohj
is certainly much less stable than the core JS scripting stuff at this point.
I'll use ohj as a starting point and combine with own scripts. For example, I've added most of the other OH triggers and conditions to the helpers... Are there already helpers in your package to schedule timers, like setTimeout in the former js helper?
For the record: I was now able to sort out the issues I reported in https://github.com/jpg0/ohj/issues/19 (basically a duplicate of this issue) with these steps:
ohj-support
addonI have just a limited set of rules defined with JS for now, but at least they are working now again w/ OH3!
I've merged https://github.com/jpg0/ohj/pull/20 and also included the fix from @LukasA83. Still not really sure why it was failing, but I'm guessing it's something related to the startup ordering issues in OH3.
hi @jpg0,
as discussed in separate thread, I tried your package, but basically I struggle on the installation, I believe.
Setup:
OH3 Build 2094 (docker debian) on Raspi, installed npm 6.14.10.
"npm i ohj" run successfully from $OPENHAB_CONF/automation/lib/javascript/community.
I created a test rule: `with(require('ohj').fluent){
}`
Somehow it seems not to work, logs:
15:06:27.278 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/openhab/conf/automation/jsr223/javascript/personal/testGraalvm.js': org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'ohj'