Scene Control Suite - Scene Control Widget

This rule is one part of a bundle designed to allow the creation, configuration, and activation of scenes using the MainUI. The three parts are:

With this widget you can add item configurations to your scenes, and update or remove those configurations. For detailed description and instructions see: the tutorial.

Dependencies:

  • This widget requires the creation of a String type proxy item.
  • This widget requires the Scene Modification rule (see above).
  • Activation of the scene created by this widget requires the Scene Activation rule (see above).

Screenshots

image

Changelog

Version 0.3

  • bug fix: color item state formatting

Version 0.2

  • added close popup button for better mobile compatibility

Version 0.1

  • initial release and testing

Resources

https://raw.githubusercontent.com/JustinGeorgi/openhab-public/main/widgets/scene_controller.yaml

3 Likes

I really think the concept of ā€˜scenesā€™ needs to be included in Main UI. This widget is a perfect example of how it should work.

I tried to put it to work but when I ā€˜add devicesā€™ and select any it does not show up in the list.
Tried 2 browsers, allowed for popups but no luck.
3.2M5 and no idea how to debug that stuff, can you give a hint please ?

Sounds like the Scene Modification Rule isnā€™t being triggered properlyā€¦

If the rule runs there should be a log entry such as ADD [item name] in [controller name]. Any evidence of that?

There was a breaking change in the rule templates recently. I havenā€™t updated the rule templates yet because I was under the impression that this was just the most recent snapshots and that 3.2M5 wasnā€™t affected, but maybe thatā€™s not the case.

Can you check your instance of the Scene Modification Rule and see if the ${...} tags have been properly replaced by the configuration values?

I didnā€™t see any of those.
Which Karaf logging would I need ?

Now given my JS setup is untested it could be a reason, too.
I have the JS scripting extension installed (and only that one, at least thatā€™s what I think).

I have created activate and modify rules from the template.
However, when I manually trigger to run the scene modification rule from UI, Iā€™m getting the following and wonder about the GraalVM output.

2021-12-16 12:36:14.250 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: ReferenceError: "scriptExtension" is not defined
        at <js>.:program(<eval>:10) ~[?:?]
        at org.graalvm.polyglot.Context.eval(Context.java:379) ~[?:?]
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?]
        at javax.script.AbstractScriptEngine.eval(Unknown Source) ~[java.scripting:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:69) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocable.eval(DelegatingScriptEngineWithInvocable.java:51) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocable.eval(InvocationInterceptingScriptEngineWithInvocable.java:69) ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:62) ~[?:?]
        at java.util.Optional.ifPresent(Unknown Source) ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:59) ~[?:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1180) ~[?:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1032) ~[?:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runNow(RuleEngineImpl.java:1048) ~[?:?]
        at org.openhab.core.automation.rest.internal.RuleResource.runNow(RuleResource.java:327) ~[?:?]

Ah. Thatā€™s it then. At the moment the rules are only compatible with Nashorn.

The rules sound like theyā€™re installed properly, so you can try Richā€™s Nashorn ā†’ JSscripting conversion:

Thanks, will try. But as you probably know, Nashorn will be dropped after Java 11 and Yannick will make a blog post on the JS state in OH 3.2 and that JS scripting is the future (if I got that right).
So wouldnā€™t it make more sense if you yourself move the whole thing to JSs so anybody to start using this would do on JSs right away rather than going for a foreseeably deprecated version thatā€™ll require migration one day ?

Thatā€™s the plan, of course, and youā€™re welcome to wait for that, but itā€™s going to take me just a little while. So if itā€™s important that you make this work for you ASAP, youā€™ll likely get slightly faster results if you want to give it a try yourself.

1 Like

Glad to hear that he will take the chance to consolidate that. Yes, we are staging JSScripting to be the default JS going forward. But at this time I think that my rule templates are the only ones that are currently compatible with both Nashorn and JSScripting. And even mine have not implemented the ${ } to {{ }} change that is the most recent change Justin just mentioned. I think the freeze happened yesterday so I plan to do that this weekend.

But the main point is until at least OH 3.2 release, rule templates will almost certainly be broken for some users in some cases. And even after that point, previously installed templates will need to be removed and re-added.

@JustinG, after a quick scan of your code I think you only need to changes to make them compatible with both Nashorn and JSScripting.

  1. Add to the top of the script the following
if(typeof(require) === "function") Object.assign(this, require('@runtime'));

That will import all the stuff you are used to using in Nashorn scripts the same way in JSScripting. That will minimize the amount of changes that need to be made to make it compatible with both. Often thatā€™s the only change required.

  1. Unfortunately thatā€™s not the only change for your scripts. scriptExtension doesnā€™t exist in JSScripting so we need to use a different class to get at the MetadataRegistry. Change:
var _bundle = FrameworkUtil.getBundle(scriptExtension.class);

with

this.ScriptHandler = Java.type("org.openhab.core.automation.module.script.rulesupport.shared.ScriptedHandler");
var _bundle = FrameworkUtil.getBundle(ScriptHandler.class);

I think thatā€™s it.

Note, these depend on the Alarm Clock Rule template which already is compatible with both but not yet working with the ${} to {{}} changes which I plan on making today or tomorrow.

Edit: I also want to add that it would be good for us to migrate to JSScripting and drop Nashorn eventually. Itā€™s way nicer to code rules with Iā€™m finding and at a minimum we can support the distribution of external libraries using npm which can make the templates even more powerful.

2 Likes

Thanks Rich, thatā€™s helpful. I hope to be able to get to this and the other change this weekend as well. I havenā€™t even put the JSScripting add-on on my system yet, so Iā€™ll need to do that for testing before I push the update out.

Iā€™ve updated the rules for the 3.2RC1 and the JSscripting compatibility. If you havenā€™t updated it yourself yet, you should be able to reinstall the template from the marketplace and get it to work.

@rlkoshak When running the rules with JSscripting I do see the following warning:

2021-12-19 16:43:41.827 [WARN ] [.internal.OpenhabGraalJSScriptEngine] - Failed to retrieve script script dependency listener from engine bindings. Script dependency tracking will be disabled.

Is this expected or did I miss something?

1 Like

No, I see that too. It still works and itā€™s a warning so Iā€™ve held off raising it as an issue for now and plan on doing it later. Based on my limited understanding it just means that the rule wonā€™t reload imported libraries if the library changes later.

1 Like

Had the same problem. You have to add the widget proxy item in the widget configuration.
This information should probably added to the description and tutorial.

Sorry Iā€™m not getting that.
Iā€™ve just started over now using the ECMA2021 version but still same problem:
when I select an item to add to the scene from the popup list, I see a confirmation (white text on black on left hand side) but it does not show up in the UI widget.
The scene(s) show up once the scene proxy item is properly define (Scene Controller tag) so why would I need to add it to the widget ? The whole point about this is the user can change scenes without modifying the widget, isnā€™t it.
What exactly do you think I need to add exactly where ?

As the tutorial topic describes (albeit not clearly it seems) both the scene modification rule and this widget only need to have the item specified if you use an item named something other than the default Rule_SceneModify.

I probably should make that clear here too, so Iā€™ll update this when Iā€™m next at a computer.

There is one additional (String) item that you need to create manually that is not one of the scene items but is just an item for transferring values between the widget and the rule. If this item is not named Rule_SceneModify then you will have to set the Rule Item parameter for the widget to the name of the item you created and also change the trigger item for the scene modification rule. You only need to do this during the initial setup of the widget then everything should work.

1 Like

It works to add devices to the scene after I created the Modification rule.
That isnā€™t really explicitly mentioned in the tutorial, please clarify there.

Glad it works, Iā€™ll see what I can do about clarifying the tutorial.

Fantastic widget!
Got it workingā€¦ just
I really like this and hope I can make it work for my smart home. And learn how the hell it is done to make more UI stuff that does this kind of thing.

I had a problem with the rule I downloaded from the OpenHAB UI. I spent hours digging through and logging the code, only discover right at the end that the Only If condition gets filled as ā€˜trueā€™ for the Scene Controller switch item rule, which only accepts ON or OFF. I also had a nightmare of a time figuring out what to name stuff to make it all link up properly. I think the instructions and naming could be improved for other people to follow along. Including the item definitions for the various items and a few template scenes would have helped a lot.

There are a few things that I think I would need to do to properly implement it. I will attempt some of it myself, but I suspect is mostly beyond my skill level. Hopefully someone else can help too.

  • The first fatal flaw is that it is quite difficult (for anyone but me, the admin/coder) to add and remove new scenes. We need a way to actually add and delete these scenes with the widget. Either by creating/editing the items required to make this work automagically, or in metadata somehow.

  • It needs to be possible to change the values of the stored states without actually changing that item. Simple enough perhaps with steppers for number items (although figuring out the right min, max, and step could be difficult), probably harder for string items?
    This is important for a few reasons:
    People want to edit scenes without annoying the rest of the house.
    Setting alarm states or other items that make noise are a problem.
    Probably more reasons as you start to try to actually make a scene.

  • Can the devices in a scene be sorted? Even better would be a way to toggle this in the widget. They are a jumbled mess in my first experiment.

  • Color code badges - Maybe green and red for switches, yellow for numbers etc

  • Add support for DateTime items, and maybe other item types I havenā€™t noticed are missing yet

  • Widget should have a scene selector built in at the top displaying the current scene

  • Widget items picker:
    Filters for searching and adding items needs reworking.
    Filters should be grouped as types of items and/or rooms - ā€˜Lightsā€™, ā€˜Fansā€™, ā€˜Heating Controlsā€™ etc. and ā€˜Kitchenā€™, Living Roomā€™ etc.
    Read-only items should not be displayed to help de-clutter, such as temperature readings, vibration sensors, sun and weather data etc.
    Items should show icons.

  • Scripts - Until now I have used a text rule to set a lot of items for a scene, but I also run a few scripts or other code beyond an item state. Could we add ā€˜rulesā€™ or ā€˜scriptsā€™ to the search results of the device picker? Even if most people canā€™t edit these, they could turn them on/off or apply existing ones to scenes.

  • Maybe how I want to use scenes is different to other people, but I would like to remove the ā€˜Enabledā€™ switches from this widget. I want to use a few scenes that are the constant rhythm of the house: DAY, EVENING, NIGHT. Then interrupt these with a scene VACANT when the house is empty, and other room or activity specific scenes such as DINNER TIME, TV TIME, STUDY TIME etc.
    This would replace the ā€˜Enabledā€™ switch that is currently used to prevent scenes from activating. I can also use the scene state of VACANT to do a number of other things in my smart home. The scene selector should not revert to ā€˜noneā€™ when using this logic so that all my rules can simply check if Scene-Selection != ā€œVACANTā€

Thatā€™s probably related to a known blip in the rules templates system. I thought I had fixed it previously. Sorry about that. I have now applied a fix. If you delete the rule template and reinstall it youā€™ll get the updated version and shouldnā€™t have this problem when you create new activation rules.

Hmmm, sorry about that. There really isnā€™t that much naming involved here: You need to create one string proxy item. If you name it Rule_SceneModify then you donā€™t have to set item parameter for the widget. If you want to name this item something else, then you just have to make sure that you set the widget parameter to whatever name you gave this proxy item.

Iā€™m quite open to suggestions if you think there something I can do to make that more clear.

This is doable. I didnā€™t do it on this widget for reasons that Iā€™m sure made sense to me at the timeā€¦

If you look at the widget and rule code for my Bayesian sensors, youā€™ll see that thereā€™s a mechanism for creating the items. Implementing something similar would fit this system as well. Iā€™ll try to find some time to work on this.

Iā€™ve spent quite a bit of time thinking about this (probably more than I should have). This is actually a lot harder than it sounds using the widgets. As you point out determining what to use for which item produces a ton of extra baggage in the widget. Thereā€™s no way to dynamically define what a component is. So, in this case, for every device listed in every scene every possible input widget would have to be included and depending on what the type of this one item actually is all the inputs that arenā€™t appropriate would be hiddenā€¦

On top of all of this, the widget actually doesnā€™t even get information about the type of each of the devices, just the name of the device and scene setting for the device from the scene metadata. The entire metadata system would have to be reworked to add that type information.

The devices are listed by passing the array returned from the metadata into an oh-repeater. At present, there is no way built-in way to sort the output of the oh-repeater.

I did, however, have the kernel of an idea the other day while working on a different widget. I havenā€™t tested anything yet, so no promises, but I may have a workaround that could achieve this. Stay tunedā€¦

See the comment about about the widget not knowing the item types. It might be possible to build a giant, nested conditional that runs enough different checks on the actual state value to work out basic type info, but it would be pretty absurd and probably not able to capture all the different built-in types.

Manually setting DateTime objects is somewhat unusual, especially as part of a scene, so I didnā€™t bother to include it originally. That said, there is nothing about how the rules work that should exclude DateTime items (Iā€™m 95% certain); itā€™s just that the item selector dialog doesnā€™t have a button for isolating those item types. You should still be able to type the name of the DateTime item into the search box and select it.

The same is true for any other item types (ok, image types probably donā€™t work at all since the rules donā€™t manipulate the raw states, but why would be be using a scene to set and image item?).

Again, this is mostly limited by what one can do within the widgets. Here is the ā€œsimpleā€ filter logic as it currently stands:

filter: "((!!vars.filterSwitch && loop.ohItem.type=='Switch') || (!!vars.filterPlayer && loop.ohItem.type=='Player') || (!!vars.filterDimmer && loop.ohItem.type=='Dimmer') || (!!vars.filterRoller && loop.ohItem.type=='Rollershutter') || (!!vars.filterColor && loop.ohItem.type=='Color') || (!!vars.filterNumber && loop.ohItem.type.substring(0,6)=='Number') || (!!vars.filterText && loop.ohItem.name.includes(vars.filterText))) ? true : false"

Including other factors further complicates that at a nearly exponential rate, if the desired complexity is even available with the limited widget expression parser.

This might be doable; that information is easily accessible in the data returned by the API.

Thereā€™s no reason reason to try and implement this (even if it were possible which I doubt). This is much more elegantly achieved via proxy items. Just set your rules to run when a proxy item receives a particular command and have that proxy item be one of the scene devices.

Iā€™m not sure I completely follow what youā€™re describing here, but it sounds like you donā€™t have to really modify this system at all for this. Just add the state of your VACANT item as a condition to any of the scene activation rules that you would like to be dependent on occupancy.