Looking for info on Rules and Scripts

Hi,

I’m picking up on my fresh OH installation again. But I’m a bit confused about how to program rules and scripts.
Do I need to create a rule in the UI and refer to a script to execute? I would like to have all my scripts and/or rules in Python, but I need a bit more info on where and how to create them and/or combine them.

I’m somewhat confused since I previously only used DSL

However, what I want to achieve is a light ON when motionsensor is triggered. After X minutes the light shall go off again. If in the meantime motion is detected again, the timer shall reset and start the x minutes again.

Thank you in advance!
/Jasper

Hi Jasper,
did you already install the add-on?

You have two options:

  • create the rule entirely in MainUI (triggers and the actual script)
  • create the rule in a seperate file in the config folder automation/jsr223 (including trigger)

These two options are entirely seperate.

But wait until one of our experts appear. Probably they will tell you that Python should not be your preferred choice.

Python is a fine choice, but Jython is not. It is best to consider Jython a dead end. Support for it is gone and the helper libraries are so far out of date, they will like be more hindrance than help (if you can even get them installed).

If python is your preference, then you won’t be making rules through the UI. You’ll want to look into HABApp which is an up-to-date, well-documented, and full-featured rules engine for OH.

If you really want your rules to be a part of the UI, then your best choices at this point are the JSscripting add-on or the JRuby add-on.

DSL is still viable and will remain so (including through the UI), however those other two offer many more features than DSL at this point, so if your rules are going to get at all complex, then moving away from DSL is the correct choice.

1 Like

Well, I’ve python running and first rule created. I’ve found a post that explained a bit more about rules and scripts.
So I now have the timer working with a python based script inside a rule…

It is a quick and dirty script, but it works for now…

I’ve seen HABapp many times, but not looked into it yet. But it’s not part of OpenHAB or?

It is a separate 3rd party addition to OH, but it is created specifically for OH with extensive OH integration. It is currently the best way to write native python rules for OH and gives you substantially more options and support than Jython.

Super! Thanks Justin…I’ll dive into it!

I’d also like to point out the existence of Rule Templates. Many simple use cases like these are implemented, in part of in total in templates, minimizing the amount of code you have to write at all.

This is a pretty common use case that could be implemented using the Threshold Alert and Open Reminder [4.0.0.0;4.9.9.9] rule template with a configuration along the lines of:

  • Triggering Group: A Group containing your Motion Sensors
  • Threshold State: ON (assuming your motion sensor reports ON when there is Motion)
  • Reschedule: true
  • Alert Delay: X minutes
  • Alert Rule: A Rule or Script that turns OFF the light
  • Initial Alert Rule: A Rule or Script that turns ON the light

All other settings leave at the default.

Alert Rule and Initial Alert Rule can be the same rule or different rules depending on how you want to implement it.

The rule will get the following passed into it (among some other stuff not relevant to this use case).

Variable Purpose
alertItem name of the Item that generated the alert
alertState current state of the Item
isAlerting boolean, when true the Item meets the threshold comparison, when false the Item exited the threshold state
isInitialAlert boolean, when true the Item just now met the threshold comparison, when `false, the Item has been in this state for awhile.

If you use the same called Rule or Script, use isInitialAlert to determine whether or not to turn ON or OFF the light.

Most of the rule templates are not as complicated as this one. But because this is a really common use case in OH with a lot of little differences it has a lot of different knobs and switches to handle all of those cases.

1 Like

Thanks Rich,
I’ll have a look into the template.

I have 3 very simple rules at the moment working. But no “renew timer” functionality in it. So 3 minutes is 3 minutes no matter if there is a movement in the meantime.

So an “upgrade” to something better is needed :wink:

PS. Where can I what I need to import from what? e.g. Import time, import datetime etc…is there documentation on that somewhere?

I’m not sure I understand what you are asking. Import into what? To install a rule template, in MainUI you navigate to Settings → Automation and click “add” next to the template you want to install. Then you can instantiate a rule based on that template when you click + from Settings → Rules.

If you are not dead set on using Python, take a look at JRuby

It is super simple to handle your requirement of “turn on a light for X minutes when motion was detected, and if more motion was detected before X expired, extend that timer for a further X minutes, so the light doesn’t turn off on you while you’re still moving around”.

Here are three “simple” versions that would do exactly what you want:

# A Simple rule for one sensor and one light
rule "Turn on kitchen light for 5 minutes when motion is detected" do
  changed Kitchen_Motion_Sensor, to: OPEN
  run do
    Kitchen_Light.ensure.on for: 5.minutes
  end
end

# A generic rule that applies to any motion sensors that belongs to a group
# by using a pattern in the naming convention: XXX_Motion_Sensor controls XXX_Light
rule "Turn on light for 5 minutes when motion is detected" do
  changed gMotionSensors.members, to: OPEN
  run do |event|
    light = event.item.name.gsub("_Motion_Sensor", "_Light")
    light&.ensure&.on for: 5.minutes
  end
end

# A rule that takes advantage of the semantic model. 
# This frees you up from having to have a specific naming convention
# Automatically find all the lights in the same room as the motion sensor
# further filters can be applied to select only certain types of lights if desired
rule "Turn on light in the room where motion is detected" do
  changed gMotionSensors.members, to: OPEN
  run do |event|
    event.item.location
         .equipments(Semantics::Lightbulb).members
         .points(Semantics::Power)
         .ensure.on for: 5.minutes
  end
end

You can copy paste what’s inside run do ... end into a UI rule if you prefer using UI rules. The “magic” happens inside for: 5.minutes. To read more about this particular feature, see: Module: OpenHAB::DSL::Items::TimedCommand — openHAB JRuby

There are many other ways to achieve what you want.

For a more advanced usage, I wrote a small helper “Motion Trigger DSL” on top of JRuby for my own needs so that I can have:

  • multiple motion sensors “working” for the same set of lights, or multiple sets of lights, e.g. sensors A, B, C will activate lights 1 and 2, sensors C or D, will activate light 3. This means sensor C will activate lights 1, 2, 3, but sensors A and B only activate lights 1, 2.
  • keep track of manual activations (turned on at the wall) as well as motion triggered,
  • not start a “motion timer” when I manually switched on the light (e.g. for a much longer “timeout”)
  • debounce it (prevent the light from switching back on immediately when I manually switched it off and moved out of the room),
  • optionally, automatically turn off the light when I’ve manually turned it on (not through motion).
  • Make it dead simple to add more motion trigger rules, or tweak existing ones

With JRuby you can also easily have a rule that alerts you when a door or window is left open for X number of minutes, and continues to do so until the door is closed

def alert_when_open(item)
  message = "Warning, the #{item.label} is #{item.state}"
  Amazon_Echo_TTS.command message
  notify message # Send notification to mobile app
end  

rule "Alert when something stays on/open" do
  changed Garage_Door, to: OPEN # A single door
  changed Bedroom_Window, to: OPEN # Another item
  changed BathRoom_Light, to: ON
  changed gAlertWhenOpen.members, to: OPEN # A whole group of sensors
  run do |event|
    # Do something here when it first opened

    after(15.minutes, id: event.item) do |timer|
      next unless [OPEN, ON].include?(event.item.state) # it's no longer open/on

      # here you can do what you want when it's been open for 15 minutes
      # e.g. call a method, or just do it right in here
      alert_when_open(event.item)

      timer.reschedule unless timer.cancelled?
    end
  end
end

You can also copy paste this rule body (inside run do .... end) into a UI rule.

The customisation possibilities are endless, e.g. you can very easily make it so the alert duration is customisable for each item

2 Likes

Highly recommend this. I have spent the past weeks converting my RuleDSL set to JRuby and it is really a blast. The (dynamic) timer handling in the background reduces your code to a minimum. The syntax is easy to learn and it let‘s you focus on what really matters IMHO. No boilerplate code must be created.