Collision between Rules Engine and 1.x-Style Rules

  • Platform information:
    • Hardware: Raspberry Pi 3 Modell B
    • OS: openHABian

Hey there!

I spent the last few Months on building up a small Sensorsnetwork. I’d like to add a few mechanisms to detect for example an offline modul with does not send data anymore. The logic behind of that should be pretty simple since the modules are constantly sending a Timestamp, each time they send Data via MQTT. I started doing this with the rules engine in the PaperUI, but came not that far, because of the rather limited logic possiblitis (limited to “When” and “only if” but nothing like a Switch() or a else or something like that). Thats why I am trying moving all the previusly gernerated Logic in the rules Engine to the 1.x Style rules, like that with the x.rule files in the rules folder under openhab2. But that simply does nothing… no matter how I create the rule, it jjust does not get executed.

rule "ControlP23" when Item testInputForRule received command then GPIO_A.sendCommand(ON) logInfo("TEST123","Binary") end

Is there a way to “Enable” rules or test if the file is even readable for openhab?

The graphic editor is essentially useless, it was never finished.

The “new” rule engine is however used for useful work in other (text based) languages, see JSR223, Jython, etc.

Yes, just look in your openhab.log
At boot time, it gives a message about each file loaded, including xxx.rules files
If you edit an xxx.rules file, shortly afterwards openHAB will notice and reload, giving another refresh message.

No message, no rules.

A common error is use of editors that save files with names like myrules.rules.txt - openHAB will ignore those.

Oh thank You very much, If I knew that I would have found my error much earlier. Somehow I misstyped at a point in past and created two files one named demo.rules and one named demo.rule

It allways said that demo.rules works, but that file was empty cause I wrote the rule into demo.rule. Oh man those tiny Errors taking so much time :laughing:

1 Like

This might denote a misunderstanding of how the PaperUI created Rules are supposed to work. First of all, everything rossko57 said is correct. PaperUI was never finished and has some significant bugs making it particularly unuseful.

But let’s assume that everything were finished and bug free.

First, let’s look at the parts of a plain old Rules DSL Rule:

rule "My rule's name"
when
    some rule trigger or
    some other rule trigger
then

    if(some condition) {

        block of code that does stuff

    }

end

All of those things exist for PaperUI Rules too:

rule "My rule's name"           // creating of the Rule itself, PaperUI also supports a description and tags

// the When... section of a PaperUI rule
when
    some rule trigger or        // Press the + icon to add triggers
    some other rule trigger     // Press the + icon to add triggers

then

// the but only if... section of a PaperUI rule, defines the conditions that must be true for the Rule to run
    if(some condition) {

// the then... section of a PaperUI rule, what happens when the Rule triggers and conditions are met
        block of code that does stuff

    }

end                            // creation of the Rule itself

So, as you can see, except for the addition of the “but only if…” clause, the over all structure is exactly the same as the old Rules DSL Rules you are used to.

So you wouldn’t see something like a “Switch” command at the top level. That is something that would occur in the “then…” clause, also called the Action. You have a bunch of options there:


So, if you want to send a command to an Item, choose “send a command”. But almost all of the time you want to do something more involved and interesting. In that case you would chose “executes a given script” at which point you will be able to select from available languages. By default you will have JavaScript (ECMA) but can install Jython or Groovy. In OH 3 Rules DSL will be an option as well. That is where you would write the block of code that does stuff goes here. For example:

Here’s a complete example from my thermostat:

Top level of the Rule:

I have one Rule trigger, two conditions and one action for this Rule.

The trigger is:

With would be equivalent to:

when
    Item HeatingCtrl receive command

The conditions are:


Notice in both cases I have actual code that checks the states of various other Items to make sure that we can run the Rule. In the second conditional, I actually take corrective action before the Rule runs

If you just need to test for the states of Items or Things status or the like there are options for that that do not include writing code, similar to the triggers above.

Finally, the action:

This is the code that actually does the work.

This Rule in Rules DSL would look like:

rule "Heating Control"
when
    Item HeatingCtrl receive command
then
    // heating isn't in the right state already
    val ok = true
    if(HeatingPin.state == receivedCommand) ok = false
    if(FanPin.state == ON && 
       FanMode.state == "AUTO" && 
       MainSwitch.state == ON && 
       FanCtrl.state == ON) ok = false

    if(!ok) return;

    // Prevent Heating and Cooling to be ON at the same time
    if(SystemType.state == 'US' &&
      CoolingPin.state == ON &&
      receivedCommand == ON) {
        logWarn("heating", "Heating has been commanded ON but the Cooling is already ON")
        CoolingCtrl.sendCommand(OFF)
        Thread::sleep(1000) // this isn't a good idea in Rules DSL but OK in Scripted Automation and I want the code to be roughly equivalent
    }

    // Controls the HeatingPin and Heating2Pin
    logInfo(heating, "Turning " + receivedCommand + " the heater: curr temp = "  + MyTemp.state +
              " setpoint = " + MinTempSetpoint.state +
               " mode = " + HeatingMode.state)
    var turnedOn = false

    // turns ON/OFF heating and the Fan (if US type) if it isn't already
    if(receivedCommand == ON){
        if(MainSwitch.state != ON) MainSwitch.sendCommand(ON)
        
        // Also turn on the Fan if US mode
        if(SystemType.state != "US") {
            if(FanMode.state != "AUTO") FanMode.sendCommand("AUTO")
            if(FanCtrl.state != OFF) FanCtrl.sendCommand(OFF)
            createTimer(now.plusSeconds(10), [ | if(HeatingPin.state != ON) HeatingPin.sendCommand(ON) ])
        }
        else if(HeatingPin.state == ON) HeatingPin.sendCommand(ON)
        if(HeatingPin.state != ON) turnedOn = true
        HeatingMode.sendCommand(HeatingMode.state)
    }
    else {
        if(HeatingPin.state != OFF) HeatingPin.sendCommand(OFF)
        if(SystemType.state == "US") {
            createTimer(now.plusSeconds(10), [ |
                if(FanCtrl.state != ON) FanCtrl.sendCommand(ON)
                val mode = if(FanPrevMode.state != "ON") "OFF" else "ON"
                FanMode.sendCommand(mode)
            ])
        }
    }

    // yadda yadda yadda second stage heating code goes here
end

To cut a long story short, PaperUI generated Rules are structured very much like and can do pretty much anything that a Rules DSL rule can do. And they do so in pretty much the same way. That’s the main reason I went to the trouble to post the above.

In OH 3 there is a whole new UI with a whole new rules editor which will make creating rules like this a first class citizen. I even saw a screen shot showing a YAML version of the Rule which will be a lot easier to share and ask for help with on this forum than screen shots and the like.