Advanced rules in jython

When the jsr223 integration was introduced, I started out creating a library that could handle interaction between rules. I have now started updating the script library to be compliant with the openhab-helper-library. How does it work?

My initial problem was that I wanted to have the ability control my lights through various rules, for instance I have one set of rules that is active when I am at home, other rules is active at night and so forth. Two rules could also control the same light, eg. when I open my door when it is dark, I want the spotlight to turn on for 2 minutes, but I also want the same light to turn on (together with another spotlight in the backyard) when somebody is at home and the outside door to the backyard is opened. A third spotlight will also turn on, when nobody is at home, it is a spotlight that the neighbours will notice :-). Just to illustrate that I have some complexity in my rules.

With jsr223 I have created a library to handle this complexity, allowing me to create rules on top of openHAB rules. Right now I have support for these rule types:

  • ScheduleRule
  • TriggerRule

I also plan to implement a SequenceRule, which I will use as a simple way of running a sequence of events (simulating presence when nobody at home)

Each rule has:

  • Input
  • Conditions
  • Output
    That is pretty much like the openHAB rules, but each rule is registered in a rule manager and in this context, each rule share the required state of the output. Lets say rule-1 and rule-2 both can turn on light-1. If both rulesturn on light-1, then the light will remain turned on, until the last rule turn off for light-1. It is simply implemented by adding a count of rules that request an item to be on. When it reaches zero it turns off.

I support the following input:

  • Contacts (OPEN / CLOSED)
  • Switches (ON/OFF)
  • Dimmer (Only as ON/OFF)

I support the following conditions:

  • ActiveNight (uses astro1 Action and Binding)
  • Contacts (OPEN / CLOSED)
  • Switches (ON/OFF)
  • Dimmer (Only as ON/OFF)
  • A jsr223 script that returns either True or False

I support the following outputs:

  • Contacts (OPEN / CLOSED)
  • Switches (ON/OFF)
  • Dimmer (Only as ON/OFF)

If the conditions is false the script will be disabled.

I plan to implement the following features:

  • Allow a script to be called as an output
  • Support for Dimmers as output (e.g. use another value than ON as active value)
  • Support more complex datatypes as triggers and conditions (e.g. Range/Percentage, Text, Number etc)
  • Support for Text as output (similar to handling Dimmers)

I still need some rework in the library, I do expect some breaking changes, but for those interested I have the library checked in in my own
GitHub repo. It isn’t documented besides from a sample config file. I have tried to follow the jsr223 library concept, so in that manner it should be straight forward. I there is some interest for this library, I will share it to the official library, but for now it is in the personal section :slight_smile:

Hope it can be helpfull for some of you.

3 Likes

Wow… thank you for this! Looks like I have good reading material for over the winter months! Once you get things finalized and documented, please submit to the helper library repo in the community section. In many ways, this has similarity in function to Area Triggers. I look forward to getting through all of it!

2 Likes

Can you give me a hint on how to document this appropriately?
I better get started, it guess it won’t be more interesting later .-)

If you do plan to submit to the helper library repo, I will need to be documented in reStructuredText, which sounds like a lot of effort, but it’s not much more than regular markdown that you’d use in GH. There is a section of the docs for the Community packages. If you get a PR going, I can give you some reST pointers. Although, you can learn a lot by looking through the docs in the repo. The ideAlarm docs are pretty intensive.

Well if somebody else than me thinks it is worth using it, then I will share it. Else I will find something else to spent my time on.

I think it would be useful even with a very simple documentation, since there is so much quantity of code to look through and learn from. The more we have in the Community section, the better. I am putting finishing touches on an addon that installs Jython (and the helper libraries). After that, I plan to put some time into dumping all of my scripts into the repo as examples.

Oh thanks for the nice word. Actually much of it has evoled from asking in the community and learning (“debugging”) the hardway with print statements. So much of the credit belongs to somebody else, I am just good at using Ctrl+C / Ctrl+V :innocent:

2 Likes

Looks very interesting. My only concern is the dependency on the Astro 1 Action. I fear that this may not continue to be supported in the long term if/when the 1.x compatibility layer is dropped.

I probably won’t have a chance to look at the code soon but will do so. I’m wondering if this can be made more generic and less focused on lighting only. I really like the idea of the rule count idea and can see benefits for other things like call for heat. But, as with dimmers, you will have to figure out how to manage conflicting calls (e.g. one Rule calls for 50% and another one calls for 75%, which one wins?). Maybe there can be rule a priority?

I think this overall approach will come pretty naturally in the UI based Rules where it will be super easy to write Rules that follow your exact input, condition, output type pattern

I agree. My problem right now is that the Astro Action best suits my needs. I was trying if I could setup a channel trigger for the Astro Binding, but it didn’t figure how to trigger this on startup (where I would need initialization of Astro data). I didn’t spent much time on it so there might be a solution. I guess it could be done somehow, just need the 10 minutes to figure it out :slight_smile:

It can be made more generic. SInce it was started about the time when the first release of the predecessor of openhab-helper-libraries I think a lot could be “optimized”. This job is in progress.

One of the reasons I didn’t implemented it (besides from time).

Can you give me a pointer,s o I can start documenting already? I really like the idea of doing it the right way from the beginning. Rework takes too much time .-)

To start, fork the repo and then clone your fork. Open it in VS Code and create the directory structure… /Sphinx/Python/Community/[friendly name].rst. Then create a directory /Sphinx/Python/Community/[friendly name]/. Take a look at /Sphinx/Python/Community/ideAlarm.rst for an example.

I know you have done some development, so I’m assuming this is all pretty straight forward. If not, I can help you through it or you can just provide the text and I can submit it for you.

1 Like

Use an Item linked to the Channel. The Item will get the DateTime of the event. That is how my Time of Day DP works, both the Rules DSL version and the Python version. In fact, my Python version doesn’t use the Channel triggers at all any more and only relies on the DateTime Items. That way it can work with any source of a date time, and not just those bindings that provide a Channel trigger at a given time. For example, you could use your Android alarm clock time which can get send to OH through the Android app as the start of the MORNING time period.

The Rules DSL version can only use Astro Channel triggers or statically defined times to drive Time of Day.

Another alternative would be to use the elevation or azimuth Channel linked to an Item. That should tell you when the sun has gone down. But even if you look at the Rules DSL version, you will see how I manage figuring out the current time of day at system started by using the Astro Item that corresponds to the Channel event.

Both versions of the code are available at [Deprecated] Design Pattern: Time Of Day. The version I submitted to the Helper Libraries uses Ephemeris so you can have different times of day for different day types.

I guess that would still require the Item to be persisted?
Or will it be initialized during startup?

In my experience Astro will populate the Item long before your Rules will start executing. I’ve never had that not happen. But if you do, then yes, persistence with restoreOnStartup would be a sufficient mitigation to ensure the Item has a value before the Rule runs.

It is not impoortant if it is ready or not when rules is executed first time. The problem will be if I need to wait until it is triggered by an event.
I think a simple way would be to either allow items to be provided in the setup, and then check if the link is correct :-). I guess that could be done programatically.
Another way to go would be to create items to store the values behind the scenes, that would also work.

The Item get’s populated with the current day’s value when the Astro binding first starts up and 30 seconds after midnight. It’s completely independent from the Channel trigger.

It sounds like it could work then.
I might prefer to create my own item, behind the scenes. because I would really like to be independent of items changing over time in a config, as well as the item could (theoretically) be manipulated in some other way.

Hmmmmm. No excuse to get started :slight_smile:
It seens quite straight forward…

Another option… the Mode (Time of Day) example may be of interest. It allows Modes to be configured in configuration.py using times and or Channels.

As I understand the Mode (Time of Day) it requires separate configuration. The Astro Action allows me to use already configured values (lat. / long. from openHAB system settings). So there is no need for any additional config, the drawback of the alternative solutions is that I need to rely on something not under my control.
I am also considering if the code from Astro Binding could be activated, the drawback of this, is that it requires Astro Binding to be installed.
There is certainly enough options, ikt is just to identify the one that best support the needs :slight_smile: