Can a rule be triggered by activating it?

I need some help understanding what is going on behind the scenes when rules are used in OH3 because there is something going on that cannot be explained by the actual rules themselves.

So here is the story. Yesterday, I set up a couple of rules controlling the lights in the bathroom and they worked fine. In a nutshell, there is one rule that turns on the lights under certain conditions and one rule that turns them off under certain conditions. The setup worked fine yesterday, but today, I started seeing this weird behavior when the lights wouldn’t stay off whenever I turned them off. Turning the lights off triggered something that would turn the lights back on.

Indeed, there is a rule that is triggered whenever the lights are turned off. But that rule obviously isn’t programmed to turn on the lights. What it does is it reactivates a rule that triggers when the door sensor state changes to “OPEN” (In case you’re wondering: the point of deactivating the rule as long as the light is on is to prevent to door sensor from turning the light back on when you just it off and open the door).

Anyway, that door sensor rule does turn on the lights when triggered, but turning on (i.e. enabling) the rule should not trigger it, right? And, of course, the door sensor was continuously on “CLOSED”, so it should not have triggered.

To rule out that this issue was unrelated to OH3 rules. I disabled all rules related to the bathroom. With all rules disabled, I was able to turn off the lights and they stayed off.

I then wanted to turn on the rules again one by one to confirm whether it is indeed the “lights turned off” rule that triggers the lights going back on (via the door sensor rule), but after all the rules had been off and turned on again, I was no longer able to reproduce the issue.

I did test whether I could get rules to trigger when being activated but under normal circumstances this is not the case. Could it be that - under certain circumstances - rules trigger when activated?

Alternatively, if the weird behaviour could be explained by some internal processes that are not visible in the foreground.

Could someone explain?

Post your rules. Without the actual code, we’d just be guessing.

It’s almost certainly something to do with your triggers, but may not be obvious at a glance.

This is not about my code but rather what is going on beyond the code.

Looking at the code for seven interrelated rules would make things more complicated than necessary. I am interested in understanding what kind of behind-the-scenes stuff is being cleared when a rule is disabled (running timers? variables? endless loops from previous executions? …) that is otherwise not cleared.

Since the rules in their current state work as expected, it would feel strange to post them and ask: “could there be something wrong with one of these rules?”

But I hear you. If the issue ever returns, I’ll take a snapshot of the rules at that moment and post them here. In the meantime, I appreciate any advice regarding my more general questions.

Indeed, I did notice that the trigger for the rule that turns on the light (and which therefore must have been part of whatever chain reaction was going on) is triggered when the door sensor changes to “OPEN”. (not: changes from CLOSED to OPEN). But I changed it to “from CLOSED to OPEN”, but either way, I don’t see how enabling the rule could trigger it.

No.

No.

Not without the code of the rules in question and the events.log at the time that the weird behavior was occurring.

I agree with @rpwong, this is a complicated setup and the primary suspect is the rule triggers.

There is no weird magic behind the scenes that trigger rules willy nilly. The trigger based off of events, or when directly called.

But based on what you’ve described, and the fact that no one else has reported anything remotely like this, it’s going to take some doing to convince us it’s not your code. And that means actually looking at the code and the events.

And even if it isn’t your code, we can’t figure out what’s going on without seeing the code and the events so we can work through the sequence .

Please please please don’t try to make things easy for us by withholding information. It’s super easy to ignore information we don’t really need. It’s frustrating to play 20 questions to pull information from you like pulling teeth. It’s infuriating when we ask for information and you insist on with holding it.

Not to be too blunt, if we ask for it, we need it. And we don’t owe you an explanation for why we need it.

There isn’t. But you’ve set up some mysterious interrelationship between these rules. You are right, we probably don’t need to see everything, but we definitely need to see the triggers, events.log, and the actions that call/enable/disable other rules. But why redact. Just give us everything. We really are good at ignoring the irrelevant stuff.

You can’t post too many details.

Thanks! It may sound stupid, but that already helps a lot.

What I had in mind were some residuals/leftover/ orphaned processes (demons from the world of magic!) or something like that. When I play with my Arduino, I work directly with the main loop of the microprocessor, so I can see in the code what’s going on, but in OH3, we’re at a much higher level, so I started wondering whether I may not be missing something.

This suspicion was triggered some time ago when I managed to get my rules into some kind of feedback loop where lights were turned on and off infinitely and the only way of stopping the demonic magic was by shutting down OH3 entirely and restarting it. The point is: disabling the rules didn’t help. The loop continued even after I had turned off the rules that initiated it.

That sense of not always being in full control was then reinforced when I realized that rules that have an active (Bockly) timer are not shown as “running” in OH3. My interpretation is that timers are sort of split off from the source rule, doing their thing in the background without OH3 showing any rule activity. (To clarify my point, consider the extreme case where a rule sets a timer to do something in six months. When it finally does its job, the activity may well seem to come “out of the blue”.)

I completely understand. But I also understand the importance of reproducibility for doing that kind of debugging. That’s why I refrained from posting code of which I am not sure whether it actually causes the issue at hand.

I was acting on the idea of a minimal working example (though the example was not code but more general level reasoning on how rules work in OH3. I guess I deviated from that principle by nevertheless providing a story about specific events to illustrate why I was asking these things.

I am sorry if I infuriated anyone. I tried to explain that I don’t mean to refuse to withhold the code but that I want to wait until the issue happens again so that I can post a version of the code where I know that it caused (or at least didn’t prevent) the issue from happening.

My events log is littered with energy consumption etc updates of the kind:

2023-02-20 11:00:59.547 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly_Plug_TV_Watt' changed from 9.5 W to 9.68 W
2023-02-20 11:01:00.156 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 271.49 W to 116.28 W
2023-02-20 11:01:00.157 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 238.2 V to 236.8 V
2023-02-20 11:01:00.159 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_PowerFactor' changed from 0.71 to 0.68
2023-02-20 11:01:00.159 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 116.28 W to 149.76 W
2023-02-20 11:01:00.160 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 236.8 V to 237.7 V
2023-02-20 11:01:00.160 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_PowerFactor' changed from 0.68 to 0.65
2023-02-20 11:01:00.160 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 149.76 W to 269.87 W
2023-02-20 11:01:00.160 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 237.7 V to 238.3 V
2023-02-20 11:01:00.160 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_PowerFactor' changed from 0.65 to 0.7
2023-02-20 11:01:00.934 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'ShellyStarplug_SignalStrength' changed from 3 to 4
2023-02-20 11:01:02.118 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'FTXshellyplugs7a2ee81921681127_Watt' changed from 59.9 W to 59.28 W
2023-02-20 11:01:02.118 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'FTXshellyplugs7a2ee81921681127_TotalEnergy' changed from 59.171 kWh to 59.172 kWh
2023-02-20 11:01:02.482 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'ShellyVVC_Temp3' changed from 41.8 °C to 41.9 °C
2023-02-20 11:01:03.629 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'FTXshellyplugs7a2ee81921681127_Watt' changed from 59.28 W to 59.43 W
2023-02-20 11:01:03.749 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'shelly1closet_Last_Heartbeat' changed from 2023-02-20T11:00:48.000+0100 to 2023-02-20T11:01:03.000+0100
2023-02-20 11:01:04.325 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'TableLights_Watt' changed from 22.51 W to 22.56 W
2023-02-20 11:01:07.289 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Computer_Watt' changed from 106.96 W to 113.35 W
2023-02-20 11:01:07.480 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'ShellyVVC_Temp3' changed from 41.9 °C to 41.8 °C
2023-02-20 11:01:12.480 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'ShellyVVC_Temp3' changed from 41.8 °C to 41.4 °C
2023-02-20 11:01:12.674 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 269.87 W to 116.9 W
2023-02-20 11:01:12.677 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_TotalEnergy' changed from 4085.939 kWh to 3248.387 kWh
2023-02-20 11:01:12.677 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 238.3 V to 237.1 V
2023-02-20 11:01:12.677 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 116.9 W to 149.77 W
2023-02-20 11:01:12.677 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_TotalEnergy' changed from 3248.387 kWh to 3360.824 kWh
2023-02-20 11:01:12.677 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 237.1 V to 237.6 V
2023-02-20 11:01:12.678 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Watt' changed from 149.77 W to 272.55 W
2023-02-20 11:01:12.678 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_TotalEnergy' changed from 3360.824 kWh to 4085.943 kWh
2023-02-20 11:01:12.678 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly3M_Voltage' changed from 237.6 V to 238.2 V
2023-02-20 11:01:12.759 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Shelly_Plug_TV_Watt' changed from 9.68 W to 9.89 W

Do you want even those?

So one thing that does happen in the background is that only one instance of a triggered rule can run at a time. If a rule is running and is triggered again, that new trigger is queued up and worked off in turn. If you end up in an infinite loop it can take longer for a rule to work them off than it takes for the triggers to queue up, meaning once you end the infinite loop it can take some time for the queued events to work off.

The kicker I think is that if you disable a rule after the queue has grown I’m not sure if it cancels the queued up events. The rule wasn’t disabled when the event occurred after all.

Yes, but also a timer isn’t actively running until the time comes for it to call the passed in function. Inbetween the time it’s created and it’s run time the Timer isn’t running, it’s in a queue awaiting it’s time to run.

If the Timer isn’t running, than neither is the Rule. Also, when a Rule is in it’s running state, it can run again (see discussion above). That would pretty much make Timers useless (you couldn’t cancel it for example).

True, except:

  1. a rule with a “Time is ” trigger would be a better choice in this use case
  2. you would have to go way out of your way to restore that Timer because the likelihood of both never restarting OH and never reloading that rule over a six month period is pretty low.

I think a good rule of thumb is to avoid timers longer than 24 hours, and even that is kind of pushing it. It takes too much work to maintain and restore Timers set for longer periods than that and there are easier ways to achieve the same result.

But you don’t know, or else you wouldn’t have had to ask. When asking about rules behavior, we always need the code and the events.log at a minimum. Sometimes we need more depending on what the problem is. Very rarely can we explain unexpected behavior without those.

Often we can work backwards into what’s going on and, if necessary, develop a test case to use to file an issue if there is a problem with the platform and not a misconfiguration of a rule.

I was mostly talking in general. I’ve given up on a number of threads because even after asking for something multiple times either ignores the requests or wants to argue about why I don’t need that information to help them.

There are lots of tools we can use to filter those out.

:person_shrugging: I don’t know what Items the rule works with so couldn’t say. But it doesn’t hurt if they are there.

^^^ this! Not sure if this played a role in the issue described in the OP, but I am looking one right now, which I would not have been able to understand without this information. It’s very important to understand that OH3 behaviour that looks like an infinite loop of rules triggering each other may just be a linear processing of queued commands.

So, is there any way of preventing that?

Let’s say the press of a button triggers a rule and the assumption for normal use is that the button is pressed once at a time, i.e. not multiple times in a row. But of course, this assumption won’t prevent people from pressing the button multiple times within a few seconds so that the rule is triggered again before the first instance of the rule has finished processing. And again, and so on.

So, for a robust setup, we want the rule to be triggered only once in that case.

My first idea would be to make the rule turn itself off, first thing after being triggered (we’ll worry about when and how to turn it back on later). But I’m not sure whether this is even possible or whether this causes other problems.

So the idea would be to prevent anything from queueing up in the first place. So if the rule is disabled before any subsequent trigger events occur, they won’t queue up, right?

Of course, this will only work if the first instance of the rule will continue running normally, even once the rule is turned off…

Don’t trigger a rule faster than the rule can process the events.

A human isn’t going to be able to press the button fast enough and often enough to cause a problem. It’s only when you have a sensor that is reporting at subsecond intervals, an infinite loop, or a rule that takes an inordinate amount of time that this will cause noticeable problems to the system.

Of course, your rule will need to be written to handle the button push case though, for example checking the states of Items, setting a Timer and ignoring events while the Timer exists, etc.

The rule will be triggered each and every time the triggering events occur. What the rule does after that point is up to you. You can choose to exit the rule immediately. If using UI rules you can set a condition to ignore the trigger. etc.

Using rule enable/disable is a powerful tool. But don’t fall into the trap where “when the only tool you have is a hammer, all problems look like nails.” This is what rule conditions are for.

The idea is:

  1. make rules that run fast
  2. use conditions to exit the rule (or just exit the rule) when there’s nothing to do (i.e. make the rule run even faster when there’s nothing to do)
  3. be careful with your rule triggers

In the normal course of events in a home automation system, the only time you should see problems with rules queueing up is because you’ve done something wrong. You’ve set up an inifinite loop somewhere for example (which I’m about 80% certain is what originally inspired this thread) or your rules run too slow (e.g. have long sleeps and the like). Otherwise, events simply do not happen fast enough to cause rules to queue up.

As an example, I have a sensor-online-detection and sensor-offline-detection pair of rules. These run every time any of my sensors reports a new reading. This means these rules run several times a second. I have no problem with the rules queueing up.

I just verified that this is the case. So that is excellent.

Based on my tests with a simple test rule, this is the case. In fact, it doesn’t matter when in the code the rule disables itself, if it is disabled when it exits, any trigger events that occurred during its execution will have no effect. Not even when the rule is eventually re-enabled.

So this is slightly inaccurate: if the rule disables itself, the rule will not trigger, even if it was still enabled when the triggering event occurred.

Interestingly, I can even when the rule disables itself at the beginning of the script and then reenables itself at the end, there will be no queue. So, instead of thinking about the disabled rules as blocking the creation of a queue, it seems to be more adequate to think of the re-enabling of the rule as clearing the queue and starting anew.

Well, the issue that I was just looking into was triggered by a young human member of my household. This may be an edge case, but, for what it’s worth, here is what happened:

  1. Opening the bathroom door triggered the lights to be turned on
  2. For whatever reason that human nevertheless pressed the light button with the intention of turning on the light.
  3. This caused the lights to go off, which in turn triggered a rule, which will set the room occupancy to “OFF” (because the bathroom has no windows, if the lights are off, we can assume that the room is vacant), but only after five seconds (explanation below).
  4. In the meantime the human realized that the first press of the button turned the lights off instead of on and therefore pressed the light button again.
  5. A few seconds later, the above-mentioned rule switched the room occupancy to “OFF”
  6. Which in turn triggered a rule that turns off the lights (because a vacant room needs no light)
  7. Which in turn triggered the human to press the button once again. etc.

So, why the delay? The occupancy is changed in the same rule that also re-activates the rule that makes the door sensor turn on the light. We need to wait a few seconds after the light was switched off before we turn that sensor rule back on so as to prevent the rule from firing when the person opens the door after having turned off the lights manually.

So, indeed, strictly speaking, the delay could be placed after the change of the occupancy state, but so far I have tended to slow down rules rather than speed them up because slow rules are easier to debug and - so I thought - more robust because they are less dependent on how fast the system processes events.

Yes, good point regarding the conditions. But at the moment, I find (self-)enabling and disabling rules quite a fascinating tool for building robust rule sets, so I think I will experiment with those…

Your rules need to be written to handle this sort of thing, either by canceling timers or rescheduling timers and the like when subsequent events occur after the first event. In typical code fasion, 20% of the code is functional and 80% handle error cases and edge cases. OH rules are not immune, particularly with such a complicated configuration as this.

This timer should have been canceled on step 4.

Using rule enable/disable is a really complicated way to handle this scenario. Use Timers.

Only these are not robust. And slowing down rules doesn’t make them robust either. Slowing them down doesn’t make them less prone to timing issues, it makes them more prone to timing issues.

Have one rule that triggers when the bathroom door changes to OPEN that turns on the light. Set a condition on the rule to only run when the occupancy is OFF.

Have another rule that triggers when the bathroom light changes. If the light changed to OFF, create a Timer for five seconds from now to set occupancy to OFF. If the light changed to ON, cancel the Timer if it exists.

With this simple approach you avoid all of the above problems. The occupancy will only go to OFF if the lights remain OFF for at least five seconds. Any subsequent events (e.g. the lights changing back to ON) will cause the timer to be canceled and the changing of the occupancy to OFF never happens.

This is a rock solid approach based off of [Deprecated] Design Pattern: Motion Sensor Timer and in fact you could achieve the above using rule templates instead of needing to write your own code. But even if you write your own code, Timers are going to be easier to implement, have fewer side effects, and be more robust than sleeps and enable/disabling of the rule will ever be.

Indeed. But a timer started in one rule can’t be cancelled from another rule, or can it? I had made a mental note that the only thing that is globally accessible are items. Is that still true?

Thanks for that! A really useful set of design patterns you have there! I think the topic title is misleading because the pattern obviously isn’t deprecated, only the code. I think you can remove the warning from the title because there is already a warning in the post itself regarding the code.

Templates are great, but there are also challenges with using templates

  1. You need to invest time in finding the right one (always risking that there is none…)
  2. You need to invest time to understand how the template works. You can learn a lot by doing that, but you may acquire even more (or more generic) knowledge if you instead learn to code the solution you are looking for.
  3. Even after having invested the time in 1. and 2., there is a chance that you may have to invest still more time in adapting the template to your needs.

I am not against templates. Quite the contrary. I was just reflecting on why I ended up not looking for ready-made solutions and came up with the above deterrents. In addition, there is path dependency at play: as a project develops over time, the need for a template may not be apparent from the start and once that need becomes apparent, you already invested time in your custom solution so that adjusting that will be easier that starting at step 1 above.

I am curious to look at the Open Reminer Rule Template to understand what it does and how that is useful for the Motion Sensor Timer. But I am even more curious about reading up on how to do state machines, in particular two interrelated state machines (light status and occupancy). Not sure when I’ll find the time…

It can if you use the cache. But you don’t need two rules and in fact this would be simpler to implement if you didn’t have two rules. Just have the one rule that triggers when the light changes to ON or OFF (two triggers) and determine whether to create the timer or cancel the timer using an if statement in the action. Then the Timer can live in the one rule and the logic is still super simple.

var timer = cache.shared.get('timer');
if(event.itemState == 'ON' && timer !== null) {
    timer.cancel();
}
else if(event.itemState == 'OFF' && timer !== null){
  timer.reschedule(time.toZDT('PT5S'));
}
else {
  cache.put('timer', actions.ScriptExecution.createTimer(time.toZDT('PT5S'), () => {
    // do occupancy stuff here
    cache.put('timer', null);
  }
}

And the above is probably more than you would need. The case where you received OFF but there is already a timer should never happen. I just included it for thoroughness. In Blockly this is super easy because I think putting the timer in the cache and all that book keeping stuff is handled in the timer block automatically. You just need to drop the timer into the script and set the properties.

Ultimately that DP is deprecated because you can just install and configure an implementation of it now. You don’t need to write the code at all. And I don’t intend to ever really go back to it and update it for OH 3 and OH 4 because it is now an installable rule template. That’s what I mean by deprecated. I almost deleted it entirely.

Since all the templates are in the same place, you’ll spend less time investigating those than investigating how to do it if you coded it yourself. It’s never waisted time to review the templates. And even if you choose to implement it yourself, you’ll have a working example with an explanation for how it works to go from in the template.

It’s always a trade off. But there are enough hard problems to solve in OH and home automation. I’d rather make it so OH users can spend their time solving home automation problems, not coding problems. But if you want to solve coding problems (there’s no problem with that) you can of course do that too.

And it’ll still be less time than trying to go at it blindly from scratch.

It’s always good to review the design pattern posts. However, if one is labeled deprecated, that’s because there is an implementation of it in a rule template or in openhab_rules_tools and for the latest explanation for how it works and working code, see that. The rest of the DP post is kept for legacy support.

Feel free to ask questions if you have any. That one in particular is one of the more complicated ones because it has a bunch of extra features (e.g. do not disturb periods, repeated reminders, ec.).

There is a design pattern on state machines (not written by me), an add-on in the marketplace (though that may only handle washing machines) and I’ve a rule template for a time driven state machine.

And just to be thorough, the Debounce rule template could be useful here as well. Instead of needing to manage the Timer yourself in a rule, you can create a proxy Item for the lights and configure Debounce to only update the proxy with OFF when the actual light Item has been OFF for five seconds.

And for examples of using some of my rule templates see How I Use Rule Templates

1 Like

I don’t want to solve coding problems, but in my experience, it’s inevitable…

I finally gave the Open Reminder Rule Template a try and after 2.5 hours, I still couldn’t get it to work. I’m getting this error

Cannot load CommonJS module: 'openhab_rules_tools'

and eventually I found this requirement

and I have no idea how to do this installation in my OH3 instance (which is running in a docker container). So, here I am, solving problems that are not home automation problems…

I appreciate your help. So here we go: how do I install openhab_rules_tools when running OH3 in a docker container?

open door reminder in jruby:

rule "open door reminder" do
  changed Door_Sensor, to: OPEN # If you just have one sensor
  changed Door_Sensors.members, to: OPEN # If you want to deal with a group of door sensors
  run do |event|
    after(15.minutes, id: [:door_reminder, event.item]) do |timer|
      next unless event.state.open?

      Voice.say "#{event.item} is open"
      timer.reschedule
    end
  end
end

You can use a UI based rule, just set up a trigger when the sensor changed to OPEN and only use the after … end block from above as your script. So this is the body of your rule:

    after(15.minutes, id: [:door_reminder, event.item]) do |timer|
      next unless event.state.open?

      Voice.say "#{event.item} is open"
      timer.reschedule
    end

For this situation, you debounce it.

Jruby offers three types of debouncing mechanisms for you to choose

Are you saying those few lines of jruby code replace the about 200 lines of js code that I can’t rund because I don’t know how to install openhab_rules_tools?

More or less, yes! I stand corrected - as @rlkoshak explained below, the template does a lot more. My ruby example just does the basic functionality.

Same way you’d install it with OH running any other way. You’ve a volume mounted into the container to /openhab/conf. Navigate to that volume, where ever it happens to be, and run npm install openhab_rules_tools from the automation/js subfolder. You could get a shell into the Docker container and run the npm command from /openhab/conf/automation/js, though you might need to install npm inside the container first.

With out specifics I can’t give you more than that. Why are you running Docker? Sometimes there’s a good reason but often when the reason is “it’s simpler” one soon discovers it really isn’t. It just moves the complexity somewhere else but it doesn’t eliminate it.

What command did you use to run the container? On what OS are you running the container?

Keep in mind that that 200 lines of JS code does a lot more than the few lines of Ruby do. It’s not an apples to apples comparison. The equivalent JS code that does exactly what that jRuby code does is:

var timer cache.private.get('timer', timer);
if(timer === null) {
  cache.private.put('timer', actions.ScriptExecution.createTimer(time.toZDT('PT15M'), () => {
    if(items[event.itemName].state == 'OPEN') {
      actions.Voice.say(event.itemName + ' is open');
      cache.private.get('timer').reschedule(time.toZDT('PT15'));
    }
  }
}
else {
  cache.private.get('timer').reschedule(time.toZDT('PT15'));
}

It’s a few lines more but it’s not 200 lines of code. Note I just typed in the above, there are likely errors. In addition, the Open Door Reminder rule template has:

  • A do not disturb period, alerts that occur during this time are delayed until the end of the period, but only if the door remains OPEN
  • Support for any Item type where you can look for one state as the alerting state
  • Extensive error checking
  • Custom times for each Item

I’m currently rewriting the rule template for OH 4 which is merging Open Door Reminder and Threshold Alert into one rule and that one is over 1000 lines of code. But fully half of that is error checking the rule’s configs and the Item’s configs.

1 Like

That is correct. But when I try to install npm, I am told that this will include 451 new packages occupying 804 MB of extra space. It looks a bit like overkill to me…

Is this really the way to go? If I install npm in the container like this, will it even persist across updates of the container image?

I appreciate your template, but installing it for reasons of simplicity and dedicating time to smart home issues doesn’t work at this point.

That sounds promising!

Yes, I suspected something like that. Hence my request for clarification.

No, it wont persist. But it may not matter. You only need it to install/upgrade the library. You can have it automatically installed into the container using executing scripts before openhab starts. If you are mounting folders from the host into the container as volumes you can install it on the host. You can skip npm and just git clone the repo and copy the files to the right place, though you’ll be on your own for upgrades.

I don’t know how you have your volumes mounted into the container. :person_shrugging:

Almost all of the complexity here is because you are running in Docker. When installed on the host npm simply needs to be installed (if not already present). On openHABian, not only is npm already installed, openhab_rules_tools is installed by default and can be installed from openhabian-config.

It’s still going to depend on openhab-js and openhab_rules_tools. And it’s well over 1000 lines at this point (half of which are error and configuration checking). But it does a whole lot more than Open Door Reminder and the older Threshold Alert did on their own also. It’s still alpha and there are a few more features I want to add (call the rule when a DateTime Item’s state is too far in the past, aggregate alerts at the Equipment level, restart the looping timers on OH restart). But even in it’s current state I’m already using it to:

  • send alerts when a door is left open for too long; repeat the alert if the door remains open, change the alerting behavior at night time
  • send an alert when a sensor stops updating for too long indicating it’s offline, don’t alert at night
  • send an alert when there has been no motion detected at my dad’s house for more than eight hours, don’t alert at night
  • turn on a smart plug connected to a humidifer when the humidity gets too low, turns it back off when the humidity rises, with hysteresis
  • turn on a light when motion is detected by the IP Camera binding only at night
  • send an alert when the humidity falls below a threshold in any room that has a humidifier but don’t alert at night
  • send an alert when a home automation relevant service goes offline (based on Network binding pings or MQTT LWT messages) but don’t alert at night

That’s a lot of milage out of one rule template. No code changes are required for any of these diverse behaviors, just configuration of the rule’s properties.

I went ahead and installed npm and the installation of the library went without problems and the rule started working immediately. :slight_smile:

Oh, I see. And the library is persisted in the mounted volume. That’s good!

But if the whole point of this was to put some files under /openhab/conf/automation/js/node_modules, couldn’t I have just copied them there?

Oh, I guess that’s what you’re saying here:

So, if npm is taking care of the updates, then I will also be on my own anyway once I pull a lew container image since that will eliminate npm. So, the bottom line is that if I want to keep this template running for the foreseeable future, I need to jump through another hoop and change the default configuration of my OH3 docker container so that a script will be executed before OH3 starts…

This is a matter of perspective. You can always say: this is very easy, but only under certain conditions. It’s true, of course.

Yes, that is quite powerful. Well done!

What is required though, is quite a high level of abstract thinking. To see the commonality between sending reminders when a door is open for too long and turning off the light when no motion is detected is not something many people intuitively grasp. And once you see the pattern, you still need to translate every setting from the open door terminology to the motion detection terminology. And for anyone who got so far, there is another little pitfall when they have to figure out the meaning of “alert state” when “Any state different from the alert state will cause the rule to run.”

(Answer: the alert state is the state in which no alerts are sent. Which translates to "the alert state is the state of the motion detector when the light is not supposed to be turned off, which translates to the “motion detected” state.)

What I’m trying to say is: the price for the power of abstract patterns is very high.

I have one more question: I noticed that the rule with the template is marked as “Running …” while the timer is counting down:

I appreciate that but it surprised me, because I thought that rules are only “running” as long as they are consuming processor time. So is this not the case?