I’ve seen that but I couldn’t think of a good use for it yet so I’ve been ignoring it. The rest of your post points to some powerful uses. I’ll have to come back to this for sure.
I’ve seen context but since it appeared to have the same information as event and event had more information so I’ve been focusing on event instead.
It might make more sense to use ctx though.
Ctx coupled with the rule chaining may be an approach to getting global vars like in Rules DSL back. I’ll need to explore.
I noticed that. But in the above case I really do b need the class so I can, for example, check if a Color Item is ON without needing to mess with getting the brightness value from the HDBType. It’s particularly useful when you have a Group of different types of lights and want to check them all as if they’re were just Switches.
So far mostly but there are some oddities where understanding that you are working with Java becomes important. For example, see the whole Group Operations section. Understanding that members is a Java Collection and not a JS array is vital to understand how to work with them with the stream methods we are used to in Rules DSL. I can’t think of any way that this can be abstracted through a library. Maybe by creating some more functions in the context that we pass the collection and function, though that would bear the stream.
The example above in the OP is copy and paste from my rule. There are no errors but runme never runs.
One thing Scott brought up is that Rule templates have just had a bug fix. I’m hoping that we can figure it a way to convert the library to a template that perhaps even gets distributed as part of OH. Then the user doesn’t need to do anything at all to install the library. They just need to create a rule with the library template and all the convenience methods will be there.
Also, there are some conflicts in the triggers library with the triggers for the JSON rules that need to be sorted out. No parts of the library that deal with triggers or rules will ever be used in JSON rules because that is handled differently.
Thanks for all the info. It’s slow going but I’m starting to get enough reason material to build some comprehensive docs so some of the more adventurous users can start to experiment…
No worries, my intent was only to explain why you have an event available in the script scope in the first place - it is actually one of the outputs of the trigger that was actually executed, which is added to the context as ctx['triggerID.event'] (most triggers are based on the event bus so they “expose” an event “variable” as an output) and then flattened- their prefix with the module ID is removed and they’re added to the scripts’ scopes as globals.
Ah, now I understand. Yes, for getStateAs OnOffType.class directly is needed!
Yes, I think too, the Library should help Beginners and should simplify daily scripting for all. We should always be guided by the simplified working methods of Rule DSL. But everything we cannot catch.
Is this something coming down the pike or something that has been removed or something you don’t know anything about.
On a related note, how does one add a tag to a Rule? There isn’t anything in PaperUII don’t see anything in the REST API. I see where I can add tags in the JSONDB files and I can add them there by hand. Since the Rule UIDs don’t exactly roll off the tongue I am assuming the use case for a library of Rules would be something like:
pull the collection of Rules with a given tag
filter/find the Rule by name
get the UID of the Rule
call rules.runNow(ruleUid)
It’s not super clean and I’d like to see something a little simpler but I can make it work like this.
But that doesn’t explain why it only appears in the javadocs and doesn’t appear in the master of ESH’s source code or at least it didn’t when I looked at it last night. When I try to call it I get a no such function error. It’s clearly there in the link you provided though. Weird.
I’m running about a week old snapshot. I’ll upgrade and try again.
Oh, wait, it’s protected. Maybe that is why I can’t call it?
Unfortunately that doesn’t help me much in the PaperUI Rules. I’ll have to submit a PR to add this to the REST API and the UI.
2018-11-23 09:32:02.666 [ERROR] [internal.handler.ScriptActionHandler] - Script execution failed: TypeError: rules.runNow is not a function in <eval> at line number 9
I haven’t used runNow, as I can just call a rules action by calling the function in JSR223-Jython, but I did a quick test and this is working. However, I didn’t see anything similar for OSGI services in the JS libraries.
from openhab import osgi
ruleEngine = osgi.get_service("org.eclipse.smarthome.automation.RuleManager")
ruleEngine.runNow("9ede01b8-bbb7-43a1-9679-1fad663b7090")
Hmmmm. It does seem that RuleManager is more appropriate for access to Rules in Rules than RuleRegistry. But I too cannot find any way to access the osgi services.
But if that is the Interface that I should be using, why isn’t rules a RuleManager instead of a RuleRegistry?
I opened a few Issues, one of which covers this problem. We’ll see what the devs have to say.
Also not that the docs in the OP indicate you should create $OH_CONF/automation/jsr223 to put the library scripts into.
Then just import the library.
Now that the library has changed a ton since this was written and there are other aspects of the PaperUI roles that makes much of this documentation invalid. I’m waiting for most of that to get done and checked in before updating theses docs.
//not working
//var pe = Java.type(“org.eclipse.smarthome.model.persistence.extensions.PersistenceExtensions”);
//works
var OffsetDateTime = Java.type(“java.time.OffsetDateTime”);
var now = function(){ return OffsetDateTime.now(); };
//i’d like to have the lastUpdate of the item, i don’t know how to achieve
//var jdt = new DateTime(items[“Beregnung_TageOhneRegen”].toString());
//var jdt = new OffsetDateTime (items[“Beregnung_TageOhneRegen”].toString());
//var prevTime = previousState(“MyItem”).timestamp;
//var MyItem = getItem(“Beregnung_TageOhneRegen”);
//works
var logger =Java.type(“org.slf4j.LoggerFactory”).getLogger(“org.eclipse.smarthome.model.script.Rules”);
logger.error(“This is an error log”);
logger.warn(“This is a warning log”);
logger.info(“This is an info log”);
logger.debug(“This is a debug log”);
logger.trace(“This is a trace log”);
//var item = ir.getItem(“Beregnung_TageOhneRegen”).lastUpdate(“influxdb”);
//var prevTime = pe.previousState(ir.getItem(“Beregnung_TageOhneRegen”)).timestamp; //logger.info(“This is an info log” + prevTime);
//var asODT = OffsetDateTime.parse(ir.getItem(“Beregnung_TageOhneRegen”).lastUpdate);
2019-06-23 16:14:29.921 [WARN ] [omation.core.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.RuntimeException: java.lang.ClassNotFoundException: org.eclipse.smarthome.model.script.actions.ScriptExecution cannot be found by com.eclipsesource.jaxrs.publisher_5.3.1.201602281253
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:521) ~[?:?]
at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1438) ~[?:?]
at jdk.nashorn.internal.runtime.Context.load(Context.java:962) ~[?:?]
at jdk.nashorn.internal.objects.Global.load(Global.java:1719) ~[?:?]
at jdk.nashorn.internal.scripts.Script$Recompilation$299$rules$cu1$restOf.:program(/etc/openhab2/automation/jsr223/jslib/rules.js:20) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:652) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:517) ~[?:?]
at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1438) ~[?:?]
at jdk.nashorn.internal.runtime.Context.load(Context.java:962) ~[?:?]
at jdk.nashorn.internal.objects.Global.load(Global.java:1719) ~[?:?]
at jdk.
var OPENHAB_CONF = Java.type("java.lang.System").getenv("OPENHAB_CONF");
load(OPENHAB_CONF + '/automation/lib/javascript/core/rules.js');
There still a lot of documentation left to be written for JS libraries, and the functionality is still evolving to get on par with Jython. An osgi.js was added 4 days ago, and I plan to add metadata.py and metadata.js later today!
2019-06-24 23:17:00.838 [INFO ] [jsr223.javascript ] - |Hello World!|
2019-06-24 23:17:00.838 [DEBUG] [e.automation.internal.RuleEngineImpl] - The rule ‘793a81f7-db03-40da-95fc-8f1a52f42340’ is executed.
2019-06-24 23:17:13.487 [DEBUG] [ipt.internal.ScriptEngineManagerImpl] - Added ScriptEngine for language ‘application/javascript’ with identifier: 19de419c-2b4c-4680-8ed6-a68a89ef2de7
2019-06-24 23:17:14.055 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2
java.lang.RuntimeException: java.lang.ClassNotFoundException: org.openhab.core.automation.util.RuleBuilder cannot be found by com.eclipsesource.jaxrs.publisher_5.3.1.201602281253
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:521) ~[?:?]
at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1438) ~[?:?]
at jdk.nashorn.internal.runtime.Context.load(Context.java:962) ~[?:?]
at jdk.nashorn.internal.objects.Global.load(Global.java:1719) ~[?:?]
at jdk.nashorn.internal.scripts.Script$Recompilation$716$rules$cu1$restOf.:program(/etc/openhab2/automation/lib/javascript/core/rules.js:16) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:652) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:517) ~[?:?]
at jdk.nashorn.internal.runtime.Context.evaluateSource(Context.java:1438) ~[?:?]
at jdk.nashorn.internal.runtime.Context.load(Context.java:962) ~[?:?]
at jdk.nashorn.internal.objects.Global.load(Global.java:1719) ~[?:?]
at jdk.nashorn.internal.scripts.Script$Recompilation$681$^eval_$cu1$restOf/842791077.:program(:2) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:652) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:513) ~[?:?]
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:517) ~[?:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:448) ~[?:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:405) ~[?:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:401) ~[?:?]
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:154) ~[?:?]
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) ~[?:?]
at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:60) ~[?:?]
at java.util.Optional.ifPresent(Optional.java:175) ~[?:?]
at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:57) ~[?:?]
at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1191) [247:org.openhab.core.automation:2.5.0.201906210304]
at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1039) [247:org.openhab.core.automation:2.5.0.201906210304]
at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1055) [247:org.openhab.core.automation:2.5.0.201906210304]
at org.openhab.core.automation.rest.internal.RuleResource.runNow(RuleResource.java:288) [251:org.openhab.core.automation.rest:2.5.0.201906210325]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:564) ~[?:?]
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [128:org.glassfish.jersey.core.jersey-common:2.22.2]
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [129:org.glassfish.jersey.core.jersey-server:2.22.2]
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [126:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [126:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [126:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [126:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [126:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) [20:com.eclipsesource.jaxrs.publisher:5.3.1.201602281253]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:873) [92:org.eclipse.jetty.servlet:9.4.18.v20190429]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542) [92:org.eclipse.jetty.servlet:9.4.18.v20190429]
at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [197:org.ops4j.pax.web.pax-web-jetty:7.2.10]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [89:org.eclipse.jetty.security:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1700) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293) [197:org.ops4j.pax.web.pax-web-jetty:7.2.10]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480) [92:org.eclipse.jetty.servlet:9.4.18.v20190429]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1667) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [197:org.ops4j.pax.web.pax-web-jetty:7.2.10]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.Server.handle(Server.java:505) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267) [91:org.eclipse.jetty.server:9.4.18.v20190429]
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) [82:org.eclipse.jetty.io:9.4.18.v20190429]
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [82:org.eclipse.jetty.io:9.4.18.v20190429]
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117) [82:org.eclipse.jetty.io:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:698) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:804) [94:org.eclipse.jetty.util:9.4.18.v20190429]
at java.lang.Thread.run(Thread.java:844) [?:?]
As for the error, my guess is that you saved the rule and then tried to execute it without triggering it first. This is a known bug (the issue has not yet been migrated over from the ESH repo). You can manually execute rules that use Scripted Actions, but you need to trigger them first after every save.
The choice is yours to make. It’s not just a decision between JavaScript and Python… it’s Nashorn and Jython. These scripting languages, including the underlying ScriptEngines and how they interact with Java, behave very differently. If you are a web developer with experience using very old versions of JS and only plan to do simple rules, then Nashorn seems like the best choice, especially once a scripting API or the helper libraries have been built out. Otherwise, you are passing up a much more powerful tool for scripted automation in Jython, and it comes with a complete set of helper libraries and documentation.