My first steps with OpenHab

For the three rules with ItemStateUpdateTrigger and ItemStateChangeTrigger I’m getting:

Error during evaluation of script 'file:/etc/openhab/automation/jsr223/javascript/personal/xxxx.js': Invalid type '{jdk.nashorn.internal.runtime.Undefined}' of configuration value!

I’m going to strip one of them down and see where it’s coming from, but the common denominator seems to be the triggers.

My triggers are declared like this:

triggers: 

    [ 

      ItemStateUpdateTrigger("AlxTrgOH_VentilationOff")

    ],

which seems right. Perhaps another parameter is required?

I chopped out all the content and I still get the error, so it’s pretty obviously the triggers. I’ll change the trigger type to be sure.

Confirmed, it’s the trigger

I removed the custom logger and still got nothing from the logInfo entries in my rules. Basically, my rules don’t appear to be running at all, not even the ones that aren’t giving errors.

It is. You have to fill in all three, but null is OK for the second if you don’t want to specify a state - at least this banishes the error.

triggers: 
    [ 
      ItemStateUpdateTrigger("Test1", null, "Test1")
    ],

Which log entries might indicate that the rule engine is doing something? After the “Loading script” entries, I see nothing. No rules appear to be running.

Hey guys, sorry I’m so late to the party, I have not had much time to spend on the forum lately.

The JS branch is maybe 60% complete and in terms of the most used features for writing rules I would say it’s 85% functional. The rule syntax has changed to line up as close as I could get to the Jython syntax. An example rule is included in my first post in the Ivan’s Helper Libraries thread.

Being a work in progress you will need to look through the code to see what’s available and how to use it. I have not updated any of the documentation yet, that will usually come last in the development cycle.

2 Likes

I hadn’t seen that thread. Is that the only example of the new-style JS rules? I’m afraid I don’t entirely follow it, or understand how it would apply to, say, timers.

Doesn’t anybody else use JS rules in OH3?

Edit: OK, so I just have to look at Jython examples. Let’s see.

I’m struggling to make sense of the Python examples. Would a timer rule look like this?

function every_minute(event) 
{
}
when("Time cron 0 0/1 * * * ?")(every_minute);
rule
(
    "Every Minute Timer",
    "Does stuff"
)(every_minute);
1 Like

I think I have to make my question even more specific: Doesn’t anybody else use JS rules using .js files in OH3?

On the one hand, it feels like it would be a good idea to go away for six months whilst the JS situation stabilises, but on the other, I feel like Zipato could collapse any day now, so I really want to get on with getting my system operational.

In the meantime, the ventilation goes back to manual programming :roll_eyes:

Yes, you’re example “every minute” rules correct. I’m assuming you skipped the load statements for brevity but they are in the file.

And yes, I should have mentioned that the Jython docs can be used as a reference. I have not ported everything over but what I have works 98% the same as Jython. I would suggest checking the JS function in the source after reading the Jython docs on it just to make sure it is there and uses the same parameters. I’ve done my best but there are differences between the languages that occasionally required me to do something a little different in JS.

You mean the load statement to load the helper libraries?

Why does triggers.js contain what look like the old-style triggers if they’re not used in this new syntax?

The rule is loaded OK, but then I get this error every minute:

Failed to execute rule '19495b7c-380b-43a3-8422-8b960ff9c111': Fail to execute action: 1

I consider this a kind of progress. At least something is trying to happen.

I’ve set logging for org.openhab.core.automation to DEBUG and restarted. I don’t know if it will tell me any more. Literally this only thing the rule does is this:

logInfo(“All-new radical minute-timer”);

So I’m not sure that’s the cause - unless logInfo has been replaced by something else?

I get this with DEBUG logging:

Failed to execute rule '6c6e1967-3801-4937-9cbc-dee217c5f977': Fail to execute action: 1
2021-07-23 12:53:00.807 [DEBUG] [e.automation.internal.RuleEngineImpl] - 
java.lang.RuntimeException: Fail to execute action: 1
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1191) ~[bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:991) [bundleFile:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:90) [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:829) [?:?]
Caused by: jdk.nashorn.internal.runtime.ECMAException: Error: An error occured while running rule Every Minute Timer(see the stack trace for details)
	at jdk.nashorn.internal.objects.NativeError.initException(NativeError.java:135) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.objects.NativeError.<init>(NativeError.java:101) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.objects.NativeError.<init>(NativeError.java:105) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.objects.NativeError.<init>(NativeError.java:109) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.objects.NativeError.constructor(NativeError.java:128) ~[jdk.scripting.nashorn:?]
	at jdk.nashorn.internal.scripts.Script$Recompilation$8175$1270AA$rules.L:11#function_rule#rule_execute(/etc/openhab/automation/lib/javascript/core/rules.js:45) ~[?:?]
	at jdk.nashorn.javaadapters.org_openhab_core_automation_module_script_rulesupport_shared_simple_SimpleRule.execute(Unknown Source) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.shared.simple.SimpleRuleActionHandlerDelegate.execute(SimpleRuleActionHandlerDelegate.java:34) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.internal.delegates.SimpleActionHandlerDelegate.execute(SimpleActionHandlerDelegate.java:59) ~[?:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1183) ~[bundleFile:?]
	... 8 more

That seems to indicate the rule itself is triggering an exception:

           try {
                    callback.apply(callback, [inputs.event]);
                } catch (e) {
                    callback.log.error(
                        get_stacktrace(e, "rule: " + (name || callback.name), -1, 1)
                    );
                    throw Error(
                        "An error occured while running rule " + (name || callback.name)
                        + "(see the stack trace for details)"
                    );
                }

since the error originates in the throw here in rules.js.

So I’m commenting out my logInfo line to see what happens.

Yep, now it “works” (it doesn’t actually do anything):

The trigger 'Time_cron_0_0_1_1d4ca4a7-a321-41e0-967a-12923498de7df7d6ba32-bb44-4261-bd0a-16bfa544b063' of rule '310ee782-8f8e-42aa-beb6-1661aab0c9f7' is triggered.
2021-07-23 13:11:01.117 [DEBUG] [e.automation.internal.RuleEngineImpl] - The rule '310ee782-8f8e-42aa-beb6-1661aab0c9f7' is executed.

So, what’s the new way of writing to the log?

I see the core .js use getLogger, but I’m not sure how that would translate to my rules.

You skimmed a little too quick through that file, you went right past the answer.

Line 31 has the getLogger definition, you get an slf4j logger instance. Docs can be found on Google for that library, but it is essentially the same implementation as the Python logger from the perspective of writing rules. Instead of logInfo() use it like log.info() after assigning var log = getLogger();.

Also you can find that stack trace in a different logger, see lines 17-22 for where that ended up. If you have a config file then the log path will be in there, otherwise it will be in the default.

What I can’t work out is that you seem to be specifying a certain log file. How do I just write to the log file that automation output is directed to?

I’m remoting to my 4K PC on an HD screen - definitely doesn’t help with skimming :roll_eyes:

You could, but you’d have to specify that as the log path in configuration.js