Timers torment

Hi, I have read umpteen articles on timers, but I’m still stuck after hours of fiddling & tweaking :frowning:
I’m on OH 3.
Scenario: Detect when wash definitely finished. Trigger rule whenever the power consumption changes, as it will during the wash cycle. Rule checks if power is down and the virtual switch ‘WashStatus’ is still ON… if true cancels any running timer, create a new timer, wait for 90 sec after which check again if power still down and WashStatus OFF. If true, then wash definitely finished so set WashStatus to OFF and send Pushover message.

I tested using a table lamp with sequence; Initially OFF - ON - OFF for 30sec - ON - OFF permanently.
Initial ON produces correct ‘wash running message’ ok.
If I move the second countdown cancel/null block to OUTSIDE the timer braces, the ‘Wash done’ message and the WashStatus OFF occur after only ~50 sec. Looks like the timer held onto the previous 30 seconds instead of cleanly restarting…?
A total of FOUR ‘delay timer created’ logs show up and FOUR ‘wash done’ pushover messages eventually arrive!!
If I move the second countdown/null block to INSIDE the timer braces, as in the screen shot, the script refuses to run at all with the error ‘Cannot refer to the non-final variable countdown inside a lambda expression’. I have seen forum solutions saying this is because the timer variable hasn’t been declared as ‘global’.
Hence my other highlighted query on screen shot, it the timer actually global where I’ve typed it? When I tried to ‘shoehorn’ it in at the very top of the code, I got loads of ‘block indentation’ errors. :exploding_head:
I’m truly demented by timers and all this chasing/cancelling/resetting… they are like ‘trying to mind mice at a cross roads’ as the Irish saying goes. :roll_eyes:
Many thanks in advance for your patience and any solutions/suggestions.

Whilst you are defining the Timer at the start of your rule, it is not Global as it is stored within the context of the rule and gets reinitialized on every call to that rule. Unfortunately under v3 DSL rules do not support Global Variables - you can use another scripting language such as Javascript which allows you to use the ‘this’ keyword to make a somewhat global (it won’t be accessible from other rules as it still runs in the rule context).

The easiest workaround for now is to leave the rule in a ‘.rules’ file - you will lose editing ability from the UI but the rule will run correctly.

Just a suggestion: I would not recommend to use timers to solve this. I use an item that stores the average consumption in the past minute and on every change I check whether it is below a threshold. The threshold is set so low that this will only happen when the machine has finished washing for about a minute. I use a Shelly plug that has a channel for the average consumption but you might as well calculate this for yourself I guess.

Hi Sunny, thanks for your reply. That’s a complete revelation!! I didn’t know that significant change in the Rules stuff had happened. I actually did have this rule, in more or less the same format, running fine as a .rules javascript in OH2. I couldn’t understand why it was going loopy like this in OH3. Jeepers, WHAT is the point of this DSL Rules being offered at all?! It starts as a friendly UI front end, then leads you into a script offering which can’t run your script … its seems very retrograde to have to go backwards to OH2 style of working and not be able to edit those rules. In my ignorance of the finer points of programming and the differences between DSL and javascript, it seems all a fine mess… how can a fundamental simple task involving timers grow to such a beast!
Thanks again for your suggestion all the same. I might have to go this route in desperation.

Hi Thomas, that’s a clever alternative fresh approach :+1: :slightly_smiling_face:
I’ll definitely experiment with that seeing as it would liberate me from that tangled-timer mess. Thanks for your idea.

What’s nice about this approach is that you can determine a status for the machine for example like this:

var threshold = new QuantityType("1.5 W")
var zero = new QuantityType("0.1 W")
if (newState <= zero) {
  events.sendCommand('washing_machine_state', 'Aus')
} else if (newState < threshold  && oldState <= zero) {
  events.sendCommand('washing_machine_state', 'Standby')
} else if (newState >= threshold  && oldState < threshold) {
  events.sendCommand('washing_machine_state', 'Waschvorgang')
} else if (newState < threshold  && oldState >= threshold) {
  events.sendCommand('washing_machine_state', 'Waschvorgang beendet')

I then use a change of this status item to notify me when the washing is finished.

Hi again, your rule is very elegant and simple!
I’m using a z wave Smart Switch 6 (as you’ll have seen in my screen shots). I unfortunately don’t have the nice built-in averages like your Shelly plugs. So I’m unsure about the the best approach. Can I use the persistence feature/syntax of say '(watts.averageSince(now.minusMinutes(1)) and assign that to a variable each time the rule triggers and compare it to the recommended thresholds? Honestly its all syntax hell to do what should be a simple, box ticking task. OH is like a Medusa.

Credits for the code go, I think, to Rlkoshak, unfortunately I don’t find the corresponding post where I got this inspiration from.

Just found this post that might be interesting for you as well. It also mentions the option to retrieve the value from the persistent history:

They are supported, just not in the UI. They still work as they always have though in .rules files.

Just to be clear, the significant change was in creating support for creating Rules DSL script actions in the MainUI at all. Rules DSL in .rules files remains the same. There are certain limitations of both the way that UI created rules are constructed and the Rules DSL language itself that makes it not wholly capable for UI created rules in all circumstances.

There is a feature called ScriptExtensions that I’ve not yet figured out how to use that might address this but I don’t know if ScriptExtensions are available from Rules DSL either. But these will let oyu share variables between rules regardless of the language it’s written in.

At a very high level, it’s because Rules DSL was never designed to be used in the way it’s used in UI created rules. The language itself lacks a number of features that would allow creation of timers like this to work. And since the language itself didn’t change between OH 2.5 and OH 3 it’s capabilities in the UI are somewhat limited.

And changing the language is not easy so it might be some time before one can access “global” variables in Rules DSL scripts.

As a general rule, if you have to ask “why can’t X just work” the answer is because you are vastly underestimating the complexity of the problem. Pretty much everyone who contributes to openHAB is competent and cares about usability. If something is hard for you as the user, it’s usually because it’s really hard for the developers to implement.

Hi Rich, I have to commend again your excellent contribution to help clarify things. :+1:
It seems that there are many of us who are struggling to fully understand and be acquainted with the fine print of OH. A case in point there now where we thought DSL Rules didn’t support global variables :upside_down_face:
I realise now I don’t really understand the difference between ‘Rules DSL’ and javascript. From what you say, it would seem advisable to just carry on writing rules as we did in those ‘.rules’ files in OH2.
Can you give me the dummies version on this so: If I ignore the Rule UI front end, and jump straight into syntax, which script window of the TWO offered, ECMAScript or Rules DSL should I use? I managed to navigate the whole rule writing business in OH2 cobbling together rules files. How/where/in what language do I write them now? I know I can import older rules files from OH2 but they aren’t editable it seems? I’m floundering a bit to be honest.
Many thanks for all the info and insights.

Rules DSL is a programming language invented by the openHAB developers for rules development. It’s based on a language called Xtend. The DSL part stands for Domain Specific Language. It was created by and for use only in openHAB.

JavaScript is a general purpose programming language. The syntax of JavaScript is significantly different from Rules DSL.

However, in each case, most of what one does in a rule is interact with openHAB. And when interacting with openHAB you are dealing with the same things, no matter the language. Consequently there is a lot the same, despite the fact that they are different languages.

What is driving you to change? Why not just continue on as you’ve been writing rules in OH 2.5? They still work in OH 3 just like they always have?

The question doesn’t really make sense. If you ignore the Rule UI front end, there is no script window to choose from. You can choose to write rules in .rules files, same as always, or you can choose to write rules in .js files using a different language (JavaScript, aka ECMAScript).

If you already know Rules DSL and will continue to writing rules in text files and you’ve not encountered something you just can’t do in Rules DSL, why change? The developers of OH actually went to quite some trouble to ensure that your .rules files continue to work just as they always have.

However, if you want to create rules in the UI, then again the question is what is driving that change? Why do you want to write them in the UI now instead of the .rules files you’ve been using all this time? and when you answer that question then the next one is what do you hope to be able to do with these rules? As evidenced here, there might be some things you can’t accomplish in one language compared to others.

And you don’t have to stick to just one language. You can use all of the supported languages in one rule if you want/need to. Each script needs to be different but you can have multiple scripts in one rule and each can be written in a different language.

So why change now?

That too is as it’s always been. If you define it in a text file, be it a Thing, an Item or a Rule, it cannot be edited from the UI. If you want to be able to edit the rules from the UI then that may indeed be a reason to migrate your rules to the UI. But it’s not just a copy and paste effort. The UI rules work a bit differently and you will have to adjust them accordingly. If using Rules DSL that may mean swapping timers for sleeps in some cases (long running rules are not so bad anymore), having a mix of some rules in the UI and others in .rules files, and potentially dipping your toe into JavaScript or Python for some rules.

Sorry, its testament to my fundamental confusion about some concepts and lingo.

Yes I’m happy enough to keep writing them in text files. So my earlier muddled question refers to this… In OH2 I used Visual Studio Code and simply created a new .rules file and started to develop the syntax etc on the code sheet that opened. Here in OH3 I’ve lost my bearings a bit… I want to effectively do the same thing again but am confused about whether I start with the Rule UI and choose a ‘script’ window or (dunno which one) or where is the equivalent language/code sheet to start directly…
If I can get this clear in my mind, I’ll be happy enough :slightly_smiling_face:

Being a Mac man I always prefer a UI if possible. I find too much time can be spent/wasted fiddling with syntax when a simple checkbox/drop down menu in a rule UI does the job painlessly. I know that not all programming can be done like that but a lot of the basics should be. Also, the new philosophy & design of OH3 is all about doing everything through the UI (which is brilliant and I’ve mostly followed btw) so it seemed logical to follow the pattern and try do the rules the same way. That was my thinking.
I haven’t experimented with Blockly yet.

Rich I’m not in the same league as yourself when it comes to programming & coding :grinning: so all that’s a bit over my head :crazy_face:

Aha! this is the nub of the question really. I guess I didn’t want to just drag in old rules and try run them, given there may be issues /modification required. I wanted to start afresh and experiment with doing everything via OH3 and have everything ‘in one place’ so to speak. I didn’t want to have to jump back and forward between Visual SC again for example. I have also experimented with Node Red (it is amazing) but I don’t like the ‘inelegance’ of tacking on yet another program/software to OH to do basic stuff which should be possible within the boundaries of OH. This is how I’ve arrived at the present conundrum.
Thanks again for all the help and interesting aspects raised.

OK so if you still have any patience remaining, a few pointers would probably sort me out and I could carry on

It can work exactly the same. Open your VSCode and edit the file in /etc/openhab/rules just as you always have.

I’ll say it again, you can continue to do everything exactly as you did in OH 2.5.

Well, in that case you can’t continue to do it exactly as you always have and will have to learn a new way. If you want to stick to the UI then you have to learn the way rules in the UI work. This is all pretty much brand new so it is unreasonable to expect it to work the same as it always used to.

A UI rule has three sections (compared to the two sections in text based rules):

  • When: the triggers
  • Then: the actions to take when the rule triggers
  • But only if: tests that can limit when the rule can run (e.g. only run when Item Foo is ON and it’s between 12:00 and 14:00 on a weekday)

In the UI the only place where you fall into writing actual code is in the Scripts (Script Actions which go under “Then” or Script Conditions which go under “But only if”). But notice that there are all sorts of other options to choose from as well. Some very simple rules can be created without any writing of code at all. For example, I have a rule that changes an IsCloudy Switch Item to ON when the weather reports it’s 50% or more cloudy outside. There is another one to switch it off when it is less than 50% cloudy. There is no code in these rules at all, it’s all just done through the UI.

If you need to do something more complicated you need to select a Script as the Action or Condition. By default you have the choice between three languages for these: Rules DSL, ECMAScript (i.e. JavaScript), and Blockly (visual programming similar to Scratch, not really complete at this time so you can only really do very simple stuff). You can install add-ons to get Python and Groovy support if desired if those languages are more familiar or desired. There is a Ruby add-on on the way I think.

These scripts will contain everything you would have put between the then and end of a text based rule in Rules DSL. So no triggers and that means there are no global variables you can share between rules. That’s a limitation for all the languages when created through the UI.

If you have a Rules DSL rule that does not rely on global variables, you should be able to paste in the code between the then and end of the rule into the Script Action and it will work (assuming you’ve adjusted it to correct the breaking changes for OH 3 such as the move to ZonedDateTime). However, if the rule depends on global variables you’ll either have to keep it in a .rules file or you’ll need to port it to JavaScript (or Python or Groovy), or you’ll need to choose an alternative approach to achieve the same result (as shown above with using the averageSince instead of a Timer).

Hi Rich,
I have learned a lot from reading (and re reading) your reply article. It’s very well put together and really clarified things. I do appreciate your time. :slightly_smiling_face:
I feel better placed now to play around with both the .rules files and the UI approach to see which suits and indeed, as you said, I may well end up with a mix of UI generated rules and text rules. regards,