Really struggling with OH 3 ECMAscript rules. Cannot find event and cannot get triggering item

Hi,
I am trying to “port” my OH2.5 DSL rules into ECMAscript and I am really finding it a challenge.

First question is do I really need to use ECMAscript?

I just wanted to do a simple get the triggering item name or label to put into a variable. I cannot do it in ECMAscript. Everything I have read says to use:

ir.getItem(event.itemName)

I got that from here: But How Do I…? — openHAB Helper Libraries documentation

When I type event and then press ctrl-space my only option is events. There is NO event.

I give up on this ECMAscript. I can get simple things to work.

Here is the code I am using and I have spent 3 days trying to crack this:
// logger.info(“About to test executeCommandLine”);
var logger = Java.type(‘org.slf4j.LoggerFactory’).getLogger(‘org.openhab.rule.’ + ctx.ruleUID);

var Exec = Java.type(“org.openhab.core.model.script.actions.Exec”);
var Duration = Java.type(“java.time.Duration”);

//The statement below doesn’t work
var device = event.itemName();

//I want to get the item that triggered the event and put it in below where it says CoffeeMachine_CoffeeMachine
//as the statement below works!
//var device = itemRegistry.getItem(‘CoffeeMachine_CoffeeMachine’).getLabel();

// var device = ItemRegistry.getItem(triggeringItem.name.toString();

var stateof = “MOVING”;

// Exec.executeCommandLine(Duration.ofSeconds(5), “/usr/bin/mosquitto_pub -h 192.168.0.164 -t cmnd/coffee/displaytext -m [zOa2f0s1l1c1]Door-garage[s3l2c1]MOVING[s1l8c1]Updated[c9]at:[c13tS]”);
// results = Exec.executeCommandLine(Duration.ofSeconds(5), “/usr/bin/mosquitto_pub”,"-h",“192.168.0.164”,"-t",“cmnd/coffee/displaytext”,"-m",mqtt,stateof,mqtt1);
results = Exec.executeCommandLine(Duration.ofSeconds(5), “/usr/bin/mosquitto_pub”,"-h",“192.168.0.164”,"-t",“cmnd/coffee/displaytext”,"-m","[zOa2f0s1l1c1]" + device + “[s3l2c1]” +stateof + “[s1l8c1]Updated[c9]at:[c13tS]”);

java.lang.Thread.sleep(10000);

Exec.executeCommandLine(Duration.ofSeconds(5), “/usr/bin/mosquitto_pub”,"-h",“192.168.0.164”,"-t",“cmnd/coffee/displaytext”,"-m","[o]");

logger.info("results = " + results);

Here is the error I get:
2021-02-05 15:42:00.159 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘5d74ea1203’ failed: ReferenceError: “event” is not defined in at line number 8

I am finding it difficult to find working examples. I just get things like use this:
ir.getItem(event.itemName)
Great but how do I use the above.

If anyone out there has managed to get something similar to work let me know.

Thanks

Hi Greg,
First thing: it will be much easier to get help on your code if you use code fences. See this post here for a quick intro:

I’ll do what I can to answer some of the questions you’ve got.

Nope. If the DSL rules have been working for you, you can keep them; DSL is even still an option if/when you upgrade to OH3. Many users find DSL too limiting and prefer one of the other options, you can accomplish most tasks with DSL.

The item registry gives rules access to all the information about every item in OH. The getItem method of the item registry takes a name of an item in string format and returns an item object that gives you access to the item’s properties. You just have to remember that getItem is returning a complex object, not a nicely formatted string with an item name or label. To get that information you then have to call (as you do in one of the examples below) one of the item methods.

event doesn’t seem to be an automatically included object. If you declare it, then it gets populated by the correct properties. If you just add var event to the top of your rule, you should fix this problem. The editor still won’t be able to complete any of the properties of the object, but it should still at least recognize event as a viable variable.

Two things here:

  1. Most of your references to event were not working, I suspect, because you hadn’t declared event
  2. The values that are populated into the event object are properties (values), not methods (functions), so you don’t need the () and instead it should just be event.itemName

This works because it is a correct usage of the getItem method with a item name string literal as the method parameter. As soon as you get the event object working you will be able to get the item name string dynamically with event.itemName. As it is already a string you won’t even need the toString just:

var device = ir.getItem(event.itemName).getLabel();

and your device variable will now be a string containing the human friendly label of the item that triggered the event.

Hope that helps get you a little further along if you decide to keep trying instead of staying with the DSL (which is OK too).

If you want to get the name of the triggering item you can use the following code:

var triggerItemName = triggeringItem.name

Hi,

I don’t have any code fence icons on the reply box. I don’t know why.
Screenshot from 2021-02-05 17-23-33
I will try the 3 back tick way and see what happens.

// logger.info("About to test executeCommandLine");
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);

var Exec = Java.type("org.openhab.core.model.script.actions.Exec");
var Duration = Java.type("java.time.Duration");
var event

//The statement below doesn't work
//var device = event.itemName;
//below doesn't work either
//var triggerItemName = triggeringItem.name;
//below doesn't work either
var device = ir.getItem(event.itemName).getLabel();


//I want to get the item that triggered the event and put it in below where it says CoffeeMachine_CoffeeMachine
//as the statement below works!
//var device = itemRegistry.getItem('CoffeeMachine_CoffeeMachine').getLabel();


// var device = ItemRegistry.getItem(triggeringItem.name.toString();


var stateof = "MOVING";


// Exec.executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub -h 192.168.0.164 -t cmnd/coffee/displaytext -m [zOa2f0s1l1c1]Door-garage[s3l2c1]MOVING[s1l8c1]Updated[c9]at:[c13tS]");
// results = Exec.executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub","\-h","192.168.0.164","\-t","cmnd/coffee/displaytext","\-m",mqtt,stateof,mqtt1);
results = Exec.executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub","\-h","192.168.0.164","\-t","cmnd/coffee/displaytext","\-m","[zOa2f0s1l1c1]" + device + "[s3l2c1]" +stateof + "[s1l8c1]Updated[c9]at:[c13tS]");

java.lang.Thread.sleep(10000);

Exec.executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub","\-h","192.168.0.164","\-t","cmnd/coffee/displaytext","\-m","[o]");

logger.info("results = " + results);

I tried all the suggestions and none of them worked. This is very frustrating. I just need an example that I can modify to my environment. I am not a javascript programmer and at this rate I never will be.

Thanks for trying suggestions.
Can you copy the code into your environment and see if it works for you?
I am obviously doing something wrong.
I want to use the javascript way because the execute command works so much better then in DSL as I had to use stringBulider to send the command and it didn’t handle spaces very well and was very messy but it worked.
Hopefully the code fence worked this time.

By the way I am doing all of this through the GUI and not files.
Maybe that is why nothing works?

I have defined all my items and things via GUI so that shouldn’t be the problem.

I modified one of my rules and this should work to get the label of the triggering item:

var triggerItemName = triggeringItem.label;
log.info("triggerItemName = " + triggerItemName);

I got the following in the log:

2021-02-05 07:53:52.572 [INFO ] [.openhab.rule.HeizkoerperControlMode] - triggerItemName = Control Modus

It doesn’t work for me.
If I just run the rule it fails…because there is no triggering item I presume?

Does the screenshot below cause a triggering item?

If it doesn’t create a triggering item then that could be the issue?

I am at a loss. It seemed so simple in theory.

This is the error if I run the rule:
2021-02-05 18:08:44.216 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘5d74ea1203’ failed: ReferenceError: “triggeringItem” is not defined in at line number 15

There must be a trick to this GUI stuff.

One additional note. event is only populated when the rule is triggered by an Item. Not when it is manually triggered nor when it is triggered by a time event.

But, when you do have the rule triggered by an Item event, event will automatically be declared and populated for you. There is no need to declare it yourself. And in fact if you declare it and initialize it you run the risk of wiping out the stuff put into event when the rule is triggered by an Item event.

Only for Rules DSL

If you are talking about executeCommandLine, then it works exactly the same in JavaScript because it’s the exact same code you are calling. So your

Exec.executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub","\-h","192.168.0.164","\-t","cmnd/coffee/displaytext","\-m","[o]");

would be

executeCommandLine(Duration.ofSeconds(5), "/usr/bin/mosquitto_pub","\-h","192.168.0.164","\-t","cmnd/coffee/displaytext","\-m","[o]")

in Rules DSL.

Now that all the arguments are passed separately instead of needing to use @@ all the issues with spaces and such go away, for Rules DSL as well as JavaScript.

triggeringItem only exists when a rule is written in Rules DSL. In JavaScript you can get the name of the Item that triggered the rule from event.

OK, moving back to the OP:

No, you don’t have to change anything. You can continue to use .rules files or you can move your Rules into the UI and choose “Rules DSL” as the language in your Script Actions.

How is the rule triggered? If you trigger it manually or by a time based event there is no event. If it is triggered by an Item then event will be passed into the Script Action and it will hold a bunch of stuff about the event that caused the rule to trigger.

First of all, simplify. Can you confirm that the rule is actually being triggered? Add logging to confirm.

Counter what JustinG suggested, do not define event as a variable. But you cant test to see if event exists using something like:

if(this.event === undefined) {
    // event does not exist
}

Again, event will only be defined when the rule is triggered by an Item event.

Before just blindly trying to use it, log it out. What do you get with:

logger.info(event.toString());
logger.info(event.itemName);
logger.info(event.itemState);

To get the Item’s label you do need to pull it from the registry first. Once you’ve verified that event.itemName is being populated, then pull the Item and see what it is.

var device = ir.getItem(event.itemName);
logger.into(device.toString());

Once you confirm that you have the Item Object and can get the label.

tl;dr:

  • except for redefining event the code looks mostly OK
  • event only exists when the rule is triggered by an Item event
  • make sure the Script Action language matches the language you are using, in this case ECMAScript.
1 Like

Here’s the rule I sometimes use for testing various things during my own script development. If I need to make sure that some particular event-driven code works, I add it to the end of this rule’s script.

This item:

when changed (in this example the item was switched `OFF’) triggers this rule:

which runs this script (note: newState is also an automatically declared variable in a rule triggered by a change of state event):

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
logger.info([itemRegistry.getItem(event.itemName).getLabel(), 'Changed From:', event.oldItemState ? event.oldItemState : 'Null', 'To:', newState].join(' '));

and results in this log output:

2021-02-05 08:09:56.512 [INFO ] [org.openhab.rule.0ef1478b17         ] - Testing Switch Changed From: ON To: OFF

I can see where my late-night edits garbled my point in my previous post. The only benefit derived from manually defining event is that this causes the UI editor to add it to the autocomplete options - something I don’t use much myself. The script will function, as far as I can tell from the few times I have done this, just as well with or without that definition. Rich may well know better for some performance reason why it is less desirable.

The biggest concern will be those users who blindly initialize everything.

var event = null;

That will wipe out the event that was passed into the rule before you even get a chance to use it.

And since I never tried it, it could have run the risk of redefining event into a narrower scope than the passed in event which would also have covered up the event that was passed into the script. But since you’ve tested it I’ll trust your results. That’s not a concern, at least for JavaScript. It might be a problem for Python or Groovy though as those handle scope a little differently I think so users beware.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.