openhab-scripters / openhab-helper-libraries

Scripts and modules for use with openHAB
Eclipse Public License 1.0
88 stars 69 forks source link

Simple/Fluent API #276

Closed jpg0 closed 4 years ago

jpg0 commented 4 years ago

Is your feature request related to a problem? Please describe. Currently the API is fairly verbose and powerful, yet I suspect most rules have very simple requirements.

Describe the solution you'd like I'd love a simplified fluent API, so that you could create rules such as:

Describe alternatives you've considered I'm currently ending up with my own personal high-level API for things that I need, but keep feeling that a more general solution could be really useful for many people.

Additional context I suggest a fluent API because it seems appropriate, but I don't think it's crucial. This is more an idea which could really help people move over to jsr223 rules, or new starters adopt them as a first rule.

rkoshak commented 4 years ago

I agree it might help new starters. I disagree that it will help Rules DSL migrators. Those users will need something that "looks" more like Rules DSL Rules, or at least has an obvious one-to-one set of concepts.

I believe the Python library has this covered with the Rule decorators:

Rules DSL:

rule "My Rule"
when
    Item Foo changed
then
    // do stuff
end

translates to

from core.rules import rule
from core.triggers import when

@rule("My Rule")
@when("Item Foo changed")
def my_rule(event):
    # do stuff

Except for the imports (which I'd like to do away with if that ever becomes possible) there is a one-to-one translation of concepts between the two languages. That will help Rules DSL migrators tremendously by reducing the number of new concepts they have to learn in order to migrate. Given my experience helping folks dealing with Group members, that sort of approach would be quite a challenge for many users to pick up and understand.

I believe the plan is to introduce similar decorator type concepts to the JavaScript when we can move to a newer JRE and therefore new ECMA version.

What if you need something much more complicated though? Rarely are anyone's Rules a simple setting of one Item to a predefined state. How would this approach work in a case like that where, for example, you need to do a multi-line calculation and have conditional branches and the like?

jpg0 commented 4 years ago

I can see why it may be better to keep as close to the rules DSL syntax for migrators.

The reason that I raised this was that I have been migrating my rules and it seemed like they follow the '80/20 rule' such that 80% are fairly simple, repetitive rules. The largest set of these were simple schedules to turn on/off lights, pumps etc at predefined times (followed by rules of type state transfer, such as proxy items or switches/contacts that operate other switches).

For each scheduling rule, of maybe 8 lines or so, scattered across many rule files (as one file would get too big), I replaced with with a single statement such as schedulesutil.turnOn('Hallway_Light', 'SUNSET'). This has massively reduced my sprawl of rules!

Additionally, as it is a sufficiently high-level API call, I was also able to add rule toggling via switch items transparently (I have a section 'Rules' in the sitemap allowing me to disable any rules, for example if I'm away or having a party etc).

I completely agree that this can in no way replace the existing API as the remaining 20% of rules are going to need all the functionality that they expose. I now know however that I'm likely to end up with the majority of my rules as simple one-liners a a file or two, and most of the code I write to support them can fairly easily be made generic and reusable.

I guess if I see sufficient demand, maybe I'll try to contribute it back. (Speaking of which, I'm not sure what the approach to populate the 'community' folders is.)

rkoshak commented 4 years ago

Well, there are generic ways to handle those types of scheduled Rules (see Time of Day and Scott's Mode Time of Day for two examples) and I and Scott have promoted such approaches as best practices. There are also plans, or at least talk on GitHub, for the creation of a robust scheduler API in OH 3 which should, if it's implemented correctly, completely replace these types of Rules entirely.

For example, see https://community.openhab.org/t/design-pattern-state-machine-driven-groups/76116, and https://openhab-scripters.github.io/openhab-helper-libraries/Python/Community/Mode%20(Time%20of%20Day).html. It actually sounds like you have yet another decent approach.

But my main point is that I'm not against this sort of way to code Rules, so long as there is also way to code Rules that look closer to Rules DSL for the migrators. I firmly believe this proposed approach is too different for those users who are not programmers themselves but have managed to cobble together a bunch of Rules DSL Rules and want to migrate to the new Rule Engine.

And even now, very simple Rules like these are super easy to create in PaperUI without the need to "code" at all. So creation of very simple Rules like this is not a completely new concept.

There is an API for enabling/disabling Rules already. Do you mean you added this ability through your library or that you've re-implemented this existing feature? https://openhab-scripters.github.io/openhab-helper-libraries/Guides/But%20How%20Do%20I.html#enable-or-disable-a-rule-by-uid

As for populating the community folders, you create a top level folder named appropriately. Under that you create an automation folder. Then you create the same folder and file structure needed to mirror where you would place the files under your $OH_CONF/automation folders for a running OH. For example, my Gatekeeper DP submission is a module instead of a script (library code, not Rules) so I put the file under Community/Gatekeeper/automation/lib/python/community/gatekeeper/gatekeeper.py. On the other hand, my Expire Binding replacement is a Script so the file went under Community/Expire/automation/jsr223/python/community/expire/expire.py

5iver commented 4 years ago

@jpg0, I'm glad you are thinking about this! The solution will be in OHC though, by introducing a Scripting API that will absorb nearly all helper library functionality. It will be language agnostic and will help with simple scripts like in your examples, and the scripting languages are there for the more complex cases like what Rich brought up. The scripted automation and the helper libraries are a great sandbox for seeing what is possible in OH automation, but those experiments need/should go back into OHC.

So, this is not the repo where a solution would be put in place. There are a few things I plan to do before getting into the Scripting API. It would be great if we could get an official OH project together so that developers could be collaborating on the changes proposed for automation. To do it right, I feel automation should be split out of OHC and have its own repo, so this would need to be something for OH 3.0. I plan to bring this up when OH 2.5.0 gets closer to release.

jpg0 commented 4 years ago

@rkoshak I forgot about the Paper-UI created rules too - agree that they are great for those with less technical experience. Also I had not seen that pattern - that's a good one.

As for the rules, my requirement is to allow toggling of the rules from the same UI as toggling of the lights etc. I do this by wrapping rule creation, so that it creates a new item for each rule (in a group), and a new rule which passes the state of the item on to the rule itself, using the API that you cited. It's all transparent when creating new rules, but means that they show up in the Basic UI automatically:

rules

So ungrouped rules at the top level, grouped ones below:

LivingRoom Lights 2019-10-25 11-56-12
jpg0 commented 4 years ago

@openhab-5iver all that makes sense - it's really useful to see that board which helps me understand the direction. I presume that this project (or something like it) will remain as the sandbox to trial approaches that make it into the scripting API?

5iver commented 4 years ago

I presume that this project (or something like it) will remain as the sandbox to trial approaches that make it into the scripting API?

Yes, I believe so. Even if core gets completely absorbed, the community packages will be around for a while. Eventually, they will be moved into an ExtensionService, similar to the Eclipse Marketplace, to make them easier to share and collaborate on, which will be a huge component of OH3.

jpg0 commented 4 years ago

Completely agree that an external source of extensions would be a great direction. It would probably also be worth considering permitting installation directly via NPM (well, a compatible impl) for JavaScript, as this is already a standard for packaging & deploying JS and would allow devs to use the existing universe of JS present in NPM. But I guess this is a long way off!

I'll close this feature request and maybe submit a fluent API if/when I build one with whatever mechanism is available at that time.