openhab / openhab-core

Core framework of openHAB
https://www.openhab.org/
Eclipse Public License 2.0
930 stars 428 forks source link

[Rules DSL] Make triggers optional #3655

Open miloit opened 1 year ago

miloit commented 1 year ago

Hello,

if you define a scene via a textfile it is not possible with the DSL rule engine.

This is not possible

rule "My Scene"
when
then
    MyItem1.sendCommand(ON)
    MyItem2.sendCommand(50)
    ...
end

with JS Rule engine everything is possible

rules.JSRule({
  name: "My Scene",
  description: "My Scene",
  triggers: [],
  execute: (event) => {

  },
  tags: ["Scene"],
  id: "my scene"
});

More information see: https://community.openhab.org/t/openhab-4-0-milestone-discussion/145133/434

openhab-bot commented 1 year ago

This issue has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/openhab-4-0-milestone-discussion/145133/437

clinique commented 1 year ago

"Offline" : I'm not sure the title is accurate. Maybe "File based" ?

kaikreuzer commented 1 year ago

Such "non-trigger" rules actually already existed since openHAB 0.6.0 - they are called "script", being put into the conf/scripts folder with the file extension .script and it is possible to call them from rules through the callScript-action.

DSL-Scripts are simply the "execution" block of a rule. They are not a rule, since they are lacking triggers. "scenes" in this sense aren't rules either - they are merely a script after all.

dathbe commented 1 year ago

I mean, couldn't you just write the rule as follows:

rule "My Scene"
when
    Item ThatDoesNotExist changed to 'Infinity'
then
    MyItem1.sendCommand(ON)
    MyItem2.sendCommand(50)
    ...
end

Voila. You now have a rule that never triggers. I have to confess, though, I've never used scripts and don't fully understand why you need a rule that does not trigger. Surely you must want it to trigger on something, and you can just write that something into the 'when' field.

J-N-K commented 1 year ago

I agree with @kaikreuzer. The "scenes" were introduced to have an easy click&play UI interface to create rules that don't do anything except setting item values. Id someone wants to define that in text files he can either create a script and call that from a rule or directly create a rule with the appropriate trigger.

hmerk commented 1 year ago

Such "non-trigger" rules actually already existed since openHAB 0.6.0 - they are called "script", being put into the conf/scripts folder with the file extension .script and it is possible to call them from rules through the callScript-action.

DSL-Scripts are simply the "execution" block of a rule. They are not a rule, since they are lacking triggers. "scenes" in this sense aren't rules either - they are merely a script after all.

How are those rules called from within a UI widget. Actually we call a scene with action: rule actionRule: sceneUID

rkoshak commented 1 year ago

being put into the conf/scripts folder with the file extension .script and it is possible to call them from rules through the callScript-action.

However, those do not show up as a "rule" to select call.

"scenes" in this sense aren't rules either - they are merely a script after all. And yet in all respects, including how they are implemented they are a rule. They are saved to the rules JSONDB file. You can change the "Scene" tag on it and it becomes just another rule. If you are sneaky/advanced, you can manually add a trigger to it from the Code tab.

I've never used scripts and don't fully understand why you need a rule that does not trigger. Surely you must want it to trigger on something, and you can just write that something into the 'when' field.

There are use cases where it's useful to be able to call a rule from another rule. For one example, most of my rule templates implement the "detect the event" part (e.g. detect a door has been open for too long) and then calls a rule/script written by the end user for what to do about it (e.g. send an alert). If the end user had to put their own code into the one rule, upgrading the template would become a real pain.

I agree with @kaikreuzer. The "scenes" were introduced to have an easy click&play UI interface to create rules that don't do anything except setting item values. Id someone wants to define that in text files he can either create a script and call that from a rule or directly create a rule with the appropriate trigger.

Which is just a way to say Scenes as they exist and are used in MainUI are not possible with text based configs. I'm OK with that but it does add a meaningful difference which will cause confusion in the future.

How are those rules called from within a UI widget.

Good point, you couldn't do that. A Rules DSL script cannot be seen from MainUI in any way so a text based scene, using the proposed solution (Rules DSL Scripts) would not support that. You could only call Scenes defined in MainUI.

J-N-K commented 1 year ago

If you look how scenes are represented in the REST API:

{
  "status": {
    "status": "IDLE",
    "statusDetail": "NONE"
  },
  "editable": true,
  "triggers": [],
  "conditions": [],
  "actions": [
    {
      "inputs": {},
      "id": "1",
      "configuration": {
        "itemName": "Dummy_Switch",
        "command": "ON"
      },
      "type": "core.ItemCommandAction"
    },
    {
      "inputs": {},
      "id": "2",
      "configuration": {
        "itemName": "BadLueftung_Ausschaltzeit",
        "command": "5"
      },
      "type": "core.ItemCommandAction"
    }
  ],
  "configuration": {},
  "configDescriptions": [],
  "uid": "14472221d2",
  "name": "Fooo",
  "tags": [
    "Scene"
  ],
  "visibility": "VISIBLE"
}

you can see that they are just a set of ItemCommandAction modules, they ARE NOT SCRIPTS. You can't add an ItemCommandAction module in a text file (at least in DSL). If you want to do that, you have to create a script that does the same (i.e. call .sendCommand on the item).

The whole thing behind the introduction of scenes was to create a simple UI way of storing current values of a set of items, like most other HA solutions do. You can't do that in a script, in no language, you always have to enter the item states manually.

miloit commented 1 year ago

Also what i think is that it should be consistent through all engines.....

J-N-K commented 1 year ago

Then let's ditch DSL. It's the only non-JSR 223 engine and therefore behaves differently from other languages.

dathbe commented 1 year ago

There are use cases where it's useful to be able to call a rule from another rule. For one example, most of my rule templates implement the "detect the event" part (e.g. detect a door has been open for too long) and then calls a rule/script written by the end user for what to do about it (e.g. send an alert). If the end user had to put their own code into the one rule, upgrading the template would become a real pain.

This does seem to be what scripts are for. But also, it would not be too cumbersome to use this workaround:

rule "Take Action"
when
    Item DoorOpenTooLong changed to ON
then
    MyItem1.sendCommand(ON)
    MyItem2.sendCommand(50)
    DoorOpenTooLong.postUpdate(OFF)
    ...
end

rule "Check Door"
when
    [cron every minute]
then
    [if door open {DoorOpenTime.postUpdate(DoorOpenTime.state + 1)}]
    [if DoorOpenTime > 30 {DoorOpenTooLong.postUpdate(ON)}]
    ...
end

Of course my syntax is all wrong, but hopefully you get the idea.

rkoshak commented 1 year ago

I'll leave the below for completeness but I just realized that https://github.com/openhab/openhab-core/pull/3156 exists and has been merged.

If I'm reading that correctly, Rules DSL Scripts actually do get exposed as rules in MainUI meaning that they can be selected from the list to be run from another rule.

If I'm interpreting that correctly, this issue is indeed can be closed as already solved. Instead of creating a rule without a trigger, create a Rules DSL Script in the $OH_CONF/scripts folder and it will appear in MainUI as a Settings -> Script and in the list of rules when selecting "Other Rules" as the action in a UI Rule or selecting a rule as the widget action.

There are a lot of ifs here that need to be confirmed but this might be more of a documentation problem, if there's any problem here at all. Over the years I think we've kind of lost the Rules DSL Scripts documentation. It's now just a few sentences under the callScript Action's docs.


I worry we are arguing about trees and missing the forrest.

In MainUI we have four different views for rules:

They have different representations in MainUI but in the end, they are all rules.

The way that Scripts and Scenes are intended to be used is to be called from other rules or from MainUI Widgets directly (or manually but that doesn't add to this discussion so I'll ignore it).

So far so good?

If we just look at file based Rules DSL we find:

Consequently, for the user who wants to stick to file based rules in Rules DSL, it is impossible to create a Scene or a Script that:

  1. can be called from another UI rule
  2. can be called directly from a MainUI widget

That's the inconsistency that I am concerned about. And 2 is the one I'm most concerned about because there isn't even a hint of a work around. It's just flat out impossible in files based Rules DSL at least.

Relaxing the requirement that all Rule DSL rules have a trigger (which actually isn't true because I can write a rule in MainUI with a Rules DSL Script Action without triggers just fine) would allow files based rules to support both 1 and 2 without any breaking changes. It seems like a pretty benign request for the sake of parity between files based and UI based rules.

The alternative would be to try to expose Rules DSL Scripts through the REST API so they could be selected and called just like a rule.

miloit commented 9 months ago

Will be there any updates in code in the future? or stays as it is?

rkoshak commented 9 months ago

I think the consensus from the above is that this already exists through Rules DSL Scripts and therefore no code changes are required. If you are using Rules DSL, a Script is the way to implement a scene.