An OH3 beginner who wants to write rules

Raspberry Pi 4 Model B Rev 1.1 / 4GB
Openhabian 3.0.1

I am looking for some basic advice on how I should approach learning and writing rules for my devices in OH3. I am coming from a SmartThings / Webcore scripting world. I know Python and have written tons of code in many languages (mostly 20 years ago :slight_smile: ) … but … much of the documentation of OH refers to OH 2 / 2.5 which I never used. Also, there are many options for rules in DSL, Jython and maybe others?

As a way to dive in and learn, I want to implement some basic rules for turning on/off lights based on motion sensor and corresponding timer activity. I have zwave, Zigbee and Hue bindings installed and I have built a basic Model of equipment etc for a few rooms of my house. I can manipulate Items (turn them on / off etc) and create very basic rules using “Create Rule” on the OH3 UI.

Does any documentation exist for getting started with OH3 and writing rules? I ask because I often am running into references to things that dont exist in OH3 (paper ui etc) … so anyway, looking for some constructive help on where I should start. I am attempting to use VS Code and have the OpenHab extension installed and working. A lot of what I am doing is poking around in the dark as I dont really know what I am doing. A “Hello World” for rules in OH3 would be very helpful if it exists.

Pointers / guidance and patience is greatly appreciated!

1 Like

With few exceptions anything written about OH 2 will apply to OH 3. There are a few minor breaking changes that you’ll have to account for when looking at examples:

  • any time you see “org.eclipse.smarthome” that has been renamed to “org.openhab”
  • Joda DateTime has been replaced with ZonedDateTime
  • the arguments to executeCommandLine have changed

If you are looking to use Python for your rules, there is an add-on to install instead of the more complicated process you may have seen before.

Anytime you see “PaperUI” there will be an equivalent feature in MainUI.

For the most part most of the docs will cover Rules DSL. Most of the examples on the forum will also be written in Rules DSL. Anything you see written about creating rules in PaperUI will also apply pretty much unchanged to rules created in MainUI. It’s all the same concepts, same languages, same approaches.

There are not a lot of UI rules examples because PaperUI wasn’t very good at creating rules so there isn’t as much about them posted anywhere. But the overall syntax is exactly the same as you see in any text based rule except you leave out the rule definition and triggers part.

So start with the Rules docs to get an understanding for how a rule is structured. Then you need to choose a language and for the most part the openHAB specific stuff will be the same between the languages with some minor differences because all the interaction with openHAB stuff is really working with Java Objects and Classes.

The only getting started docs for UI rules that exist right now is at [wiki] Getting Started with OH3: rewriting the tutorial - 8. Rules. Follow the link at the bottom to see a more comprehensive part of the tutorial showing how it all works together. Intermediate steps have not yet been written.

3 Likes

Thank you Rich for your helpful suggestions… I’ll start there and see how far I can get. Much appreciated! It’s a journey :slight_smile: I remain committed!

If you want to write rules in python there is always HABApp. It’s easy yet very flexible and powerful an provides type hints so you can use it with an IDE.

2 Likes

Yes, writing in Python would/might be my goal as I do have other automation stuff running on Pis currently with my ST setup.

Right now, I’m trying to get a basic DSL Rules working with a simple sensor and light. I am finally understanding the syntax (I’ve not done much Java Script) … and it’s starting to click! (frustration level is dropping :slight_smile: )

Related question: What is the advantage of going the Python (Jython) route? Won’t I will still need to become fluent in Java Script? Any opinion about just sticking with Java vs mixing the two?

Note that what Sebastian is recommending is HABApp. This is a separate service that runs along side openHAB and provides pure Python 3 rules support. It interacts with openHAB through its REST API. It is not the same thing as the embedded Jython rules.

The only real advantage of going the Jython route over JavaScript is that the Helper Libraries are more mature for Jython at this time, though work is being done to bring the JavaScript version up to the same level. Beyond that, whether you are using Rules DSL, JavaScript, Jython or the experimental jRuby rules languages, basically what you are doing is scripting together some logic around interactions with openHAB (updating Items, getting the state of an Item, calling actions, creating Timers, etc.). All of these interactions with openHAB are taking place through Java Classes and Objects. So, for the most part, rules from one language to the next will work and look largely the same, just with slightly different syntax (jRuby is a bit more different from the others though).

So, to create a Timer in Rules DSL you’ll have:

    createTimer(now.plusMinutes(5), [ |
        // do something
    ])

and in Jython it will be

from org.openhab.core.model.actions import ScriptExecution
from java.time import ZonedDateTime

def runme():
    // do something
    
ScriptExecution.createTimer(ZonedDateTime.now().plusMinutes(5), lambda: runme())

and in JavaScript it will be

var ScriptExecution = Java.type("org.openhab.core.model.actions.ScriptExecution");
var ZoneDateTime = Java.type("java.time.ZonedDateTime");

var runme = function(){
    // do something
};

ScriptExecution.createTimer(ZonedDateTime.now().plusMinutes(5), runme);

NOTE: I just typed in the above, there are likely errors.

Except for the fact that Rules DSL already automatically imports a bunch of stuff for you (as well as a lot of other “magic”) they are very much the same.

Here’s another example:

MyItem.sendCommand(ON) // Rules DSL

events.sendCommand("MyItem", "ON") # Python

events.sendCommand("MyItem", "ON") // JavaScript

I can’t imagine why. If you choose not to use JavaScript as a rules language you will not need to know JavaScript for anything else.

While there is a little bit of work going on to be able to write rules in Java, that is not ready for prime time and more experimental than jRuby support right now. To be clear, in OH 3.1 M3 and before the only officially supported built in languages (i.e. those that come with OH by default or can be installed via an add-on through MainUI) are Rules DSL (which is a dialect of Xtend), Jython 2.7, Nashorn JavaScript (ECMAScript 5.1), and Groovy (which I’m told is actually the closes to Java among the four). And in all of these languages, all interactions with openHAB itself will be done through Java Classes and Objects, but the syntax is very different from Java, since they are actually not Java.

In general it’s recommended against using more than one way to do something, but I see no down side to using more than one language in rules beyond the extra mental load it takes to read and understand multiple languages at the same time.

Edit: There were indeed typos

3 Likes

There was a post that compared HABApp to the built in jython that I can’t seem to find.
Biggest difference is jython is a java implementation of python that is syntactically python 2,
HABApp is a rule engine written in python3 that provides full type hints so you get auto complete and error checks in your IDE.
It takes a different approach how to create rules and (since I’ve created it :wink: ) I think it’s a better and easier one. Also it comes with many built in goodies like an advanced yet easy scheduler, parameter files that allow reloading of values independent of rules, very nice tracebacks in cases of errors, etc.

1 Like

Hi Rich - That’s a hell of a detailed response, thank you! I’ll need to work through your explanation. Clearly I am still confused on some concepts. I’ll need to play around some more. I was mistaking the Rules DSL code for Javascript, I see now that it is its own language (based on Xbase/Xtend).

I am now able to write and understand some Rules DSL code for controlling lights based on motion and timers. I will attempt to do the same using Python or Jython.

I’m also appreciating the power of properly naming of the Items/Things (I know RTFM :slight_smile: ) … I am sort of hunting and pecking my way through the docs trying to understand stuff. I am just fooling around now so I’m fine breaking things and redoing them.

Again, thanks for your responses (Rich and Sebastian)!

James

Hi Sabastian - Ok I’m trying to get HABapp working following the docs (Installation & Usage — HABApp beta documentation).

I installed HABApp from the console (I’m using openhabian), but the docs refer to a directory /opt/openhab/conf/habapp but there is no openhab directory… there is /opt/openhabian but there is no conf directory there either.

So clearly I am confused. I see the “Hint: With openhabian the installation …” … but do I still need to perform steps 1 to 7 as well, I’m assuming no. (I did try to run them and got all sorts of warnings)

I am using VS Code as the IDE … I am assuming I will be able to write the python code from VS Code and get the OpenHab hints etc. …

Should the rules I write show up in the Main UI? Do I test them from Main UI and use the OpenHab log viewer (Frontail)?

I’ll keep plugging along …

The HABApp installation is available through the openhabian-config tool.
Is there any reason you chose not to use it?

That’s the directory where you want to place your HABApp configuration and rules. You have to create it.
Create a folder named habapp in your openhab configuration folder.
Maybe it’s located in /etc/openhab?

No - they will not show up in main ui. You can use the normal python loggers to log information from your rules. In the HABApp.log you’ll see all sort of information what is currently happening.
Normally HABApp will automatically detect your logging folder and create a HABApp.log and a HABAppEvents.log in your log folder (the log folder of openhab).

Thanks Sabastian - Yes I installed it per instructions from the Openhabian Console (option 2b). What was unclear from the doc was if I was also supposed to follow steps 1 to 7 … looks like I should have just done step 7 after creating the conf/habapp/ directory. The term “console” referred to Openhabian console and I know you meant it to mean linux command line.

I was also confused as to where I would use Habapp … let me give it another try and report back.

You can check the status and start/stop/restart with:

sudo systemctl start habapp.service
sudo systemctl stop habapp.service
sudo systemctl restart habapp.service
sudo systemctl status habapp.service

It should actually already run after the installation.

You create rules in the habapp/rule folder. These get loaded and executed by HABApp.
In these rules you do all your automation logic.

Ok made a little more progress - the docs are not that clear (not meant as criticism) regarding how to get things running … not there yet but I needed to:
(This is specific to my case)

  1. edit the /srv/openhab-conf/habapp/config.yml file:
    • Specify host as openhabian.local
    • Add an API token from openhabian to the user and leave the password field blank
    • Leave mqtt user/password blank as I have not configured mqtt
  2. Create the directories for: params, lib, config … these go in the /srv/openhab-conf/habapp directory

I don’t need to run step 7 (as I incorrectly stated above) since using systemctl will start/stop the service

Not running yet, but making much better progress.

Don’t worry - I’m aware they are far from perfect.
The Docs can and should always be improved but … time … :slight_smile:

localhost is fine, too.

Yes, I forgot I’m actually executing on the target :slight_smile: … ok made a little more progress, I see the service started and in the /var/log/syslog I can see HABApp running … but I get error:

Apr 28 08:26:11 openhabian systemd[1]: Started HABApp.
Apr 28 08:26:12 openhabian habapp[8390]: Error loading logging config: Unable to configure handler 'EventFile'
Apr 28 08:26:15 openhabian habapp[8390]: Status 404 for PUT http://openhabian.local:8080/rest/items/HABApp_Ping/state/ NULL

The Ping error is happening every 10 seconds (per the config.yml file)

My logging.yml file has the default:

  EventFile:
    class: HABApp.core.lib.handler.MidnightRotatingFileHandler
    filename: 'HABApp_events.log'
    maxBytes: 1_048_576
    backupCount: 3

    formatter: HABApp_format
    level: DEBUG

Any suggestions of what I might be missing? When I look at /var/log/openhab/HABApp.log I dont see the current execution (I see entries from when I ran it manually i.e. not as the service.

James

You have to create a NumberItem with the name HABApp_Ping on the openhab side since the ping is set to enabled in the config.yml.

Ok got it … added that item and its now updating every 10 seconds (whew) … Still have something wrong with the EventFile: … in syslog see:
Apr 28 08:50:18 openhabian habapp[9049]: Error loading logging config: Unable to configure handler 'EventFile'

Could you post the whole file? Have you made any changes - it should actually run out of the box.

No, I haven’t made any changes … I’m suspecting permission issues … here’s the file:

levels:
  WARNING: WARN

formatters:
  HABApp_format:
    format: '[%(asctime)s] [%(name)25s] %(levelname)8s | %(message)s'

  Frontail_format:
    format: '%(asctime)s.%(msecs)03d [%(levelname)-5s] [%(name)-36s] - %(message)s'
    datefmt: '%Y-%m-%d %H:%M:%S'

handlers:
  # There are several Handlers available:
  #  - logging.handlers.RotatingFileHandler:
  #    Will rotate when the file reaches a certain size (see python logging documentation for args)
  #  - HABApp.core.lib.handler.MidnightRotatingFileHandler:
  #    Will wait until the file reaches a certain size and then rotate on midnight
  #  - More handlers:
  #    https://docs.python.org/3/library/logging.handlers.html#rotatingfilehandler

  HABApp_default:
    class: HABApp.core.lib.handler.MidnightRotatingFileHandler
    filename: '/var/log/openhab/HABApp.log'
    maxBytes: 1_048_576
    backupCount: 3

    formatter: Frontail_format
    level: DEBUG

  EventFile:
    class: HABApp.core.lib.handler.MidnightRotatingFileHandler
    filename: 'HABApp_events.log'
    maxBytes: 1_048_576
    backupCount: 3

    formatter: HABApp_format
    level: DEBUG

  BufferEventFile:
    class: logging.handlers.MemoryHandler
    capacity: 10
    formatter: HABApp_format
    target: EventFile
    level: DEBUG


loggers:
  HABApp:
    level: INFO
    handlers:
      - HABApp_default
    propagate: False

  HABApp.EventBus:
    level: INFO
    handlers:
      - BufferEventFile
    propagate: False

can you change the filename to '/srv/openhab2-logs/HABApp.log' ?
Maybe the path has changed since I last implemented the default.