Issues with implicit variables newState and triggeringItem in 3.0.0

Yes, everything in DSL in the “global” context (actually only global within this rules file) cannot “see” other global objects… So when you call function X from a rule, and it needs to use function Y, you must pass a reference to that in the call.

I’ve no recommendation. OH3 continues to support DSL rules, which in turn continues to have the same limitations, that in their turn are usually completely avoidable.
If you want to use exotic (for home automation) programming techniques, that might not suit.

Jython rules are flavour of the month, likely to be the standard for OH3, but you don’t like that and it doesn’t yet appear to be set in concrete anyway.

Yes, everything in DSL in the “global” context (actually only global within this rules file) cannot “see” other global objects… So when you call function X from a rule, and it needs to use function Y, you must pass a reference to that in the call.

Oh thanks for that explanation. That also means I can move that as a local val in the main function. Maybe not worth it for these two lines of code, but good to know.

If you want to use exotic (for home automation) programming techniques, that might not suit.

Yeah, I understand. I wish one could write things like this as simple extensions, say in JavaScript or whatever that could then be used by the whole framework. Or even if it had to be done in Java, that’d be fine (though slower to prototype, at least from where I stand right now).

While the code may be exotic in a way, the notion itself (multiple taps) is trivial and definitely something that is common on switches. It’s natural to want to be able to use that on controls where it’s not native.

Jython rules are flavour of the month, likely to be the standard for OH3, but you don’t like that and it doesn’t yet appear to be set in concrete anyway.

Well I just wish my brain didn’t have to think about Python 2.7 vs Python 3 when writing any Python :smiley:. But that wouldn’t be the end of the world. It’s not like I breathe Python anyways.

Yes, others are ahead of you. This one of the reasons that OH3 has a new rule engine and the jython implementation features libraries.

Okay, let’s work on that.
What are you trying to achieve? Ignore how you think of going about it.
What’s the starting point here? You are receiving trigger events from a binding, or state updates to an Item, or?

Yes, others are ahead of you.

I am sure! openHAB is pretty impressive.

Okay, let’s work on [the notion of multiple taps].
What are you trying to achieve? Ignore how you think of going about it.
What’s the starting point here? You are receiving trigger events from a binding, or state updates to an Item, or?

In this case I am receiving changes from an item:

rule "Kitchen scene All Off"
when
  Item KitchenLights_Keypad_Button3 changed to OFF
then
  updatePatternsRecognizer.apply(states, KitchenLights_Keypad_Button3, newState, newHashMap(
      'OFF,OFF' -> [| Countertops_Switch.sendCommand(OFF) ]))
end

and I am interesting in triggering an action (what would be the then part of a rule if I could write something like Item KitchenLights_Keypad_Button3 changed to OFF and OFF (or some better syntax for something like this). The sequence of changes has to happen within a predetermined time (e.g. every state change has to be, say, within 600 ms) so that I could have a rule for a double tap and a different one for a triple tap etc. for the same item.

Alright, I have to guess that this technology updates Item to ON when pressed and updates to OFF when released. They do not all work like that.


// global timer
var Timer buttonTimer = null

rule "detect press"
when
   Item myButton changed to ON
then
   logInfo("test", "button pressed, don't know if it might get pressed again")
   if (buttonTimer === null) {
         // start a timer
      buttonTimer = createTimer(now.plusMillis(600)) [ |
            // if timer expires
         logInfo"test", "it was a SINGLE button press")
         if (myButton.state == ON) {
               logInfo"test", "and they're still holding it down")
         }
         buttonTimer = null
      ]
   } else {
         // within timer window
      logInfo"test", "button DOUBLE pressed")
      buttonTimer.cancel
      buttonTimer = null
   }
end

It’s scalable to many Items using Groups, member of triggers, implicit variables (which it seems need fixing in OH3 new engine).
EDIT - ooh you’d need a Map (array) for button timers, see Rich’s Design Patterns

Alright this may work, but who wants to copy/paste and edit this every time they want to handle a double tap? In my current rules file, I have lots of such cases, and they all are a two-lines readable rule calling one function, not ten lines of code, that, if I came up with a better mousetrap, or a different log format, or whatever, I’d want to update many times.

And if I wanted three taps, this code would become pretty unwieldy and/or brittle. The lambda can’t access a var outside of it, I believe, so would you have have to prop up a similar code path for that next tap?

I hear you, it’s probably possible, and timers with lambdas are one way to have code “in the air” waiting to be executed. I was going for a building block that can be used simply in multiple places.

EDIT - ooh you’d need a Map (array) for button timers, see Rich’s Design Patterns

From this post? Also an array is akin to a list, not a map (which has keys mapping to values), so not sure I get what you are talking about.

Maybe you meant a map as in:

var Map<Item, Timer> timerMap = newHashMap

and then use triggeringItem (once that works) as the key for the timer for that source?

Why, does it cost you very much?
It’s a home automation system.
Why isn’t the button doing double tap detection for you? Many do. How many of these limited feature buttons did you buy?

The point is you can do this kind of work with DSL, however clumsy you find it. It has been around years, but is now being put to graze as a “legacy” system. There really is no point grizzling about it.

When you have specific problems, people will be happy to help.

Sure. That applies to functions in DSL too, as you have found out.

If you like. That is why it said (array) in brackets.

When you have specific problems, people will be happy to help.

I see that and appreciate it. Thanks.

This may be of interest…

1 Like

That’s the first of a series of a few dozen posts. Search on the forum is currently broken unfortunately so the link to them isn’t working from that post. So see https://community.openhab.org/tags/c/tutorials-examples/solutions/50/designpattern for a list of some of the DPs that have been tagged as such. I’ve written a lot of them but others have contributed too. Here is a site search from duck-duck-go that shows more of them.

Several DPs could apply (in no particular order:

There are a couple of state machine DPs as well which might be useful.

Almost all of the time a Map is used in Rules with the name of the Item being the key and the Timer associated with that Item as the value. That lets you have one Rule that handles the behavior for lots of Items. You can get the name of the Item that triggered the rule with triggeringItem.name.

But notice I said the name, not the Item itself as the key. I never looked into it way back when but I definitely ran into troubles when I used the Item as the key. The hash seems to change for the Item Object over time so from one run of the rule to the next the Item may no longer be able to pull the value out of the Map.

If you are on OH 3, than I believe you can get at the triggering Item using ir.getItem(event.name) but this is mainly going on some comments on on the GitHub Issue for triggeringItem not working. I’ve not tried this from Rules DSL in OH 3 and can’t guarantee it will work. But that’s how you would do it in Jython or JavaScript.

You can get the name of the Item that triggered the rule with triggeringItem.name. But notice I said the name, not the Item itself as the key.

Got it. Names are fine, they’re unique too. I haven’t run into that issue in my function (the key to my map is a SwitchItem) but I believe you :slight_smile:. Maybe the hash changes if some item properties change…

As you mentioned (and as my post started), triggeringItem is null in rules in OH 3 right now. I’ll try ir.getItem(event.name) instead. What does ir stand for? Is that am official new OH 3 implicit variable, or just a bit of implementation you’re exposing to help here?

ir stands for “Item Registry”. It’s used pretty extensively in Jython, JavaScript, and Groovy rules to gain access to actual Items, for example to get at the members of a Group. But there is also and items dict that one can use to get an Item’s state by the Item’s name. For example items[event.itemName] will give you the state of the Item that triggered the Rule (don’t do that for command triggered rules, the Item may not have changed state yet).

Now that Rules DSL is running on the new rules engine (formerly the experimental next-gen rules engine), these variables get injected into Rules DSL rules just like they have in Jython, JavaScript, and Groovy rules for quite some time.

Does that give me the state, or the item? Not knowing anything I’d expect an Item given the items variable name (and items[event.itemName].state the state).

BTW, neither ir nor items seem to be working for me (OH 3 build #1989):

Script execution of rule with UID 'update_patterns-3' failed: The name 'ir' cannot be resolved to an item or type; line 235, column 49, length 2 in update_patterns
Script execution of rule with UID 'update_patterns-3' failed: The name 'items' cannot be resolved to an item or type; line 236, column 49, length 21 in update_patterns

The state, just like I said.

if(items["MySwitch"] == ON) {

Well, it was a shot in the dark. Because Rules DSL imports event I figured it might import ir and items too. I guess not. If you ever find a need to get access to the ir from Rules DSL see Design Pattern: Associated Items (scroll down to the Item Registry section).

Ok I looked at that example. ScriptServiceUtil has moved to org.openhab.core.model.script which is fine. Are the OH 3 JavaDocs somewhere on the Web?

However, I still have another issue, that the event variable isn’t an implicit variable in DSL rules in OH3 apparently (probably because if it were, ir etc. would also be). So it looks like I’m stuck duplicating rules for now until triggeringItem is available in OH3, and it would indeed be awesome to see the other variables too. Or maybe I’ll try Jython as the scripting solution du jour (I see lots of Jython around, and not really any JavaScript for example).

I don’t know. I usually just search the github repo directly. I’m sure it is somewhere though, but can’t say whether it’s OH 2 or OH 3. Any time you see org.eclipse.smarthome anywhere, that has moved in OH 3. Usually is as easy as replacing that with org.openhab.

Hmmmm. I’m certain I saw Kai mention that it was there in the issue where the missing triggeringItem variable problem is being worked. I guess maybe I’m wrong or it’s only there if you are running a snapshot?

DSL has a receivedEvent, which is conditional and not the general event.

I am running 3.0.0-SNAPSHOT build #1989. Not sure if that matches your definition of “running a snapshot though.”

receivedEvent is only available for channel-based triggers, which I don’t think my state changed to OFF trigger is, correct?

It’s got snapshot in the name :wink:

receivedEvent is different from event. In the other languages all rules triggered by an Item or Channel Trigger have an event variable. Inside that you will find command, newState, etc.