[SOLVED] First stab at Jython

Where is this explained in the documentation? I am just a little slow wrapping my head around things.

https://openhab-scripters.github.io/openhab-helper-libraries/Guides/Rules.html#function

1 Like

I have not used decorators before in Python. Is i OK to use this thread as I develop my other rules? I am thinking of another case where I think 4 rules could become one.
Basically I am migrating from an M3 Pi system to an M4 VM system with a better Z-Wave controller. I figured I could migrate the rules to Jython & then actually move the Things to minimize service disruption. This rule is just the first piece but I only have 2 main services & a third planned currently.

I don’t have a problem with it. Though there are two schools of thought. One topic per thread makes it easier for others to find. But sometimes seeing a narrative is also useful.

1 Like

Thanks. I asked in another thread how to get & use your Expire library.
With those two I should be able to code rules for an outdoor light / motion sensor only working if it is dark & turning off 5 minutes after last motion detected.

Or you could try this :slight_smile:…

I think that is probably overkill right now for me. Thanks for sharing the idea, though.

It would take minutes to copy a few files, customize the configuration, setup your Items and groups, and then you’d be done and all setup to easily add more automations in the future. IMO, building everything from scratch is overkill :roll_eyes:! Let us know how that new wheel rolls!

Right now, I have:

  1. outdoor light & sensor triggered only when Dark & on for 5 minutes after last motion
  2. Basement stairway light with 2 sensors, off 2 minutes after last motion
  3. 3 Plugs (lights) on twice a day based on time & sunrise/sunset.

One thing I will say about Expire with Jython Rules. The benefits of Expire Based Timers pretty much disappear in Python Rules. So if you are mainly using Expire instead of Timers, you will probably be better off going to use Timers instead.

If you have situations where you have one Timer per Item, look at the Timer Manager PR I submitted to the Helper Library as well. It handles managing those for you pretty easily.

It does take a good deal of time and effort to figure out how something like that works. At first glance, I could see how a number of users would say to themselves “I don’t need all that, it’ll be easier to just do it myself.” I see it all the time with even the Rules DSL version of Time of Day.

You and I both know that it’s definitely worth the little bit of effort up front to learn and use libraries like that, but lots of OH users don’t have the benefit of our experience. :wink:

1 Like

I am still taking baby steps here. This is the DSL I am trying to eliminate next with MyTimer being a 5 minute expiry timer.

rule "Papillon Motion On"
when
    Item papillon_motion changed from OFF to ON
then
    if (IsItDark.state == ON) {
        papillon_light.sendCommand(ON)
        // start Timer
        MyTimer.sendCommand(ON)
    }
end

rule "Papillon Motion Off"
when
    Item MyTimer changed from ON to OFF
then
    papillon_light.sendCommand(OFF)
end

I’m just trying to turn you around as you toddle off in a direction that will be more effort :slightly_smiling_face:. The area trigger code handles all of this for you… the timers, mode (ToD) and lux are built in.

For this last one, add the Items to groups and then set some metadata (doesn’t look like you’re using a lux sensor)…

set_metadata("papillon_light", "area_triggers_and_actions", {
    "modes": {
        "Day": {"brightness": 98},
        "Night": {"brightness": 98}
    },
    "actions": {
        "light_action": {"OFF": {"delay": 300}}
    }
}, overwrite=True)

In configuration.mode_dict, use…

mode_dict = OrderedDict([
    ("Day", {"channel": "astro:sun:local:rise#event", "event": "START"}),
    ("Night"  , {"channel": "astro:sun:local:set#event", "event": "START"})
])

I could, but I am using that IsItDark switch.

Which is mode (ToD) functionality

The day & night in the astro binding did not look suitable.
Perhaps I can digest your code later., as I test it.
When I tested your code earlier today, I understood the logic behind it.

That is not what I was referring to. I meant this… https://openhab-scripters.github.io/openhab-helper-libraries/Python/Community/Mode%20(Time%20of%20Day).html, which is used by area triggers.

I’ll tell you what… post your DSL rules and the Items, and I will setup your groups and metadata. It will be useful for others too. Or not… I don’t want to sound pushy… whatever works for you!

I can post the rules now but do not have access to the Items text files remotely. They are pretty basic anyway.

BasementTimer is a 2 minute expiry timer.

rule "Basement Light On"
when
    Item basement_motion_1 changed from OFF to ON or Item basement_motion_2 changed from OFF to ON
then
    basement_light.sendCommand(ON)
    // start or reset Timer
    BasementTimer.sendCommand(ON)
end

rule "Basement Light Off"
when
    Item BasementTimer changed from ON to OFF
then
    basement_light.sendCommand(OFF)
end

Now the messy ones.

rule "Plug_Sunset"
when
    Channel "astro:sun:local:set#event" triggered START 
then
    christmas_lights.sendCommand(ON)
end

rule "Plug_Night"
when
    Time cron "0 30 21 ? * *"
then
    christmas_lights.sendCommand(OFF)
end

rule "Plug_Morning"
when
    Time cron "0 45 05 ? * *"
then
    christmas_lights.sendCommand(ON)
end

rule "Plug_Sunrise"
when
    Channel "astro:sun:local:rise#event" triggered START
then
    christmas_lights.sendCommand(OFF)
end

A straight forward port of these Rules is pretty simple.

from core.rules import rule
from core.triggers import when
from core.actions import ScriptExecution
from org.joda.time import DateTime

@rule("Papillon Motion", description="turn on the light for 5 minutes on motion but only at night.")
@when("Item papillon_motion changed")
def papillon_motion(event):
    if items["IsItDark"] == ON:
        events.sendCommand("papillon_light", "ON")
        ScriptExecution.createTimer(DateTime.now().plusMinutes(5), 
                                    lambda: events.sendCommand("papillon_light", "OFF"))

I just typed in the above, there may be errors. The code for stuff like this, as you can see, is pretty easy. But the advantage of learning how to use something like Scott’s Mode library is that when you decided to get more complicated, it’s much less work. A little bit of work up front can save more work later on.

One of the things that we will be pushing for in the near future is a change in OH culture to move away from needing to copy/paste/edit and understand code examples to building up complicated Rules using libraries containing code you never have to touch, just use. That’s why I’ve submitted a bunch of PRs for basic building blocks and some simple things like Gatekeeper, Timer Manager, and Generic Presence Detection.

If those are the messy ones we have a very different definition of “messy.” :wink:

I meant messy Newbie code. not difficult rules.
Actually, 1 & 3 were translated from my Home Assistant daze ;).

It works. I do not understand the lambda concept though.
Does the timer get refreshed on every motion change like my old rule?