Add/delete Group Members in Blockly?

I am struggling through the different syntax (ECMA 5.1, ECMA 11, DSL). I am a beginner, so for many examples I don’t even know which syntax it is. Accordingly, I use Blockly where possible. Which code does Blockly actually generate, ECMA 5.1?

Anyway, I am not getting anywhere at this point:

I should know the syntax to add an item to a group in a Blockly Block “Inline Script” and add a member to the group accordingly. Unfortunately I can’t do it.

I also cannot implement this example: [Javascript: how to dynamically add items to groups? - #2 by Gonzo666

"use strict";
var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.rule." + ctx.ruleUID);

var dynamicGroup = ir.getItem("gDoorOverdue");
var triggeritem = ir.getItem(event.itemName);

if (event.itemState == "ON") {
  triggeritem.addGroupName("gDoorOverdue");
  dynamicGroup.addMember(triggeritem);
  dynamicGroup.setState(ON);
  
} else {
  triggeritem.removeGroupName("gDoorOverdue");
  dynamicGroup.removeMember(triggeritem);
}

I always get errors whether I try to run this in ECMA or DSL. Even deleting the first line “use strict” ( whose meaning I don’t understand) doesn’t lead to any success.

What I am actually trying to implement is:

I have defined a scene for light.

Now I want to switch the scene to inactive if the condition for the scene is no longer true.

I want to trigger a rule when the status of an item in the scene changes.

To do this, I wanted to add the associated items to a group when the scene is activated.
And on an update in this group then start the “Scene still valid?” rule.

But I can’t add or remove an item from/to a group in Blockly and I can’t do it with the “Inline Script” block.
Alternatively I could write the items that belong to the scene into metadata. I can do this in Blockly. But how do I find out if an item of the scene has changed? I can’t use metadata to trigger a rule.

Do I have a wrong approach or just not the right syntax?

If you want to turn on/off certain number of lights, just create a fixed group and you can turn everything on/off at once.

Not sure if I understand correct what you want, but got turning on/off lights this looks over engineered

1 Like

Hello Matthias
Thank you for your answer. It is indeed not easy to understand what I mean:

If the condition for a scene is no longer true, the scene switch should be set to OFF.

Example
I have a scene with 3 lights and I turn on the scene with the “Scene Switch” = “ON”. The status of the lights is now as follows:

Light 1 = 10%
Light 2 = 20%
Light 3 = 30%

If now light 2 is switched off (light 2 = 0%), the “Scene Switch should switch to OFF”, because the conditions for the scene are no longer given.

Since I have many different scenes and things, I don’t want to query all scenes for their validity every time I update a lamp. Also I want that a new scene can be defined without modifying the code/model.

For this I need the possibility to mark the things that are currently valid for an active scene. So that when one of these marked things is updated, the scene in which they are defined can be checked for validity and deactivated if necessary.
For this the tags would be well suited, but I can’t write them and they should be replaced with the metadata. The metadata on the other hand I can write/read, but I don’t know how to use them as a trigger for a rule.
That’s why I had the idea to dynamically assign the active things of a scene to a group. Even if I know that this solution is not very elegant. But even this does not work for me.I cannot get the right syntax.

Unfortunately I didn’t document all my different syntax attempts. But I need something similar to this (wrong) example:

Scenes_Active_Items.addGroupName("LivingroomReading_brightness");

Error = "Scenes_Active_Items" is not defined

I hope I could clarify my question a little bit.

Thanks for the insights.
Independent if you use tags or metadata, you cannot trigger a rule by this.
Also the target of building a complete flexible rule that will require no code change if you want to change something is questionable and I would think about the effort “building the rule” vs “changing the rule if you add / change a scene” and how often you will modify scenes.

Overall I would keep it simple and do the following:

  1. having a switch item for each scene representing your scenes state
  2. having a group item for each scene including all items that will control the scene (and add the scene switch from 1 as meta data, that the group stores the info, which scene item is representing the scenes state) - think about naming syntax or tagging to differentiate scene related groups from any other group an item is a member of
  3. setup a rule triggered by any change of a group member of these rules and within the rule:
  1. get all relevant scene groups the item that has changed is member of (in case one item is part of multiple scenes, you need check ON/OFF state of any scenes that are affected)
  2. for each scene group, iterate through all members and check current state vs target state
  3. if one items current state != target state, set scene to OFF, otherwise to ON

Target state of each item can either be defined in the item as metadata or in a map within your rule.

When you:

  1. Want to add new scenes you would need to create a new switch item, a new group item, update your rule to include the new rule as trigger and maintain the group & target state information
  2. Want to modify existing scenes you need to add / remove items to a group and modify target state information
1 Like

Yes, for now. Eventually it will produce 2021 and use the openhab-js library.

This is a really advanced thing and there are only a few cases where this approach makes sense over alternative solutions. This smells a whole lot like an XY Problem.

That’s ECMAScript 5.1. without seeing the errors it’s impossible to say what’s wrong.

Using the JS Scripting add-on it would be as simple as:

items.getItem(triggeringItem.name).addGroups('gDoorOverdue');

openHAB is event driven. When the light changes, trigger a rule based on that event and recalculate the scene state.

Have you seen Scene Control Suite - Scene Activation?

Typically tags are used for this. But Groups could be used too. It’s still not clear though why Items would need to have their Group membership changed on the fly. The Scene is either ON or it’s not. When an Item changes state away from a scene, that doesn’t mean it’s no longer a part of that scene, it just means that scene is no longer active.

Well that’s a different problem. Why can’t you write them?

1 Like

Thanks for your answers!

Unfortunately this command just doesn’t work for me in the JS Scripting add-on. I get the error message :

items.getItem is not a function in <eval>.

Which by the way was also the error message in my other attempts. No matter if I tried to write a tag or if I tried to add a member to a group.

With much, much time and patience I found the solution for me now. Why it has to be like this, I can’t say :wink:

itemRegistry.getItem('MemberItem').addGroupName('ParentGroupItem');

itemRegistry.getItem('MemberItem').removeGroupName('ParentGroupItem');

It is quite possible that my approach is not quite “coherent” with the Openhab logic. The future will show if this means that I will be confronted with “unsolvable” problems. For now I find the solution ok for my requirement. But I fully understand your arguments.

Why I define this group:
The Scene_Active_Items group is not defined as a group of all items that appear in scenes. But as a group of all items that are present in scenes AND currently fulfill the conditions of all active (switched on) scenes. So I only have to check the validity of the switched scenes when a member of the Scene_Active_Items group receives a command.

Yes, I have seen and use the Scene Control Suite from Justin. It helped me a lot to get an understanding of everything. And now I am trying to optimize it for my purposes.

Thanks again for your guidance - I was really desperate and your answers gave me new optimism that a solution is possible!

Then you are not using the JS Scripting add-on or you are using an older version of OH prior to 3.2. What language did you choose when you created the Action? It has to be ECMAScript 2021.

Because you are using ECMAScript 5.1 instead of JS Scripting. If you were using JS Scripting it would complain that itemRegistry doesn’t exist.

1 Like

I have installed the JS Scripting add-on and my OH version is 3.2.0.M1.
It seems that Blockly still writes in ECMAScript 5.1? When I start a new script with Blockly, I have no choice:

Or do I have to change some setting?

The good thing is that now I know how to detect an ECMAScpript 2021.

Sorry to be so demanding of you. But I am really very grateful for the time and patience you spend so that I can benefit from your knowledge!

Btw: The solution to my problem is:

Using ECMAScript 5.1:

itemRegistry.getItem('MemberItem').addGroupName('ParentGroupItem');

itemRegistry.getItem('MemberItem').removeGroupName('ParentGroupItem');

With ECMAScript2021

items.getItem(triggeringItem.name).addGroups('gDoorOverdue');

Yes, as I said above…

1 Like

Yes, you have already written it, but I did not read it correctly.

I misunderstood you and thought that with the JS Scripting add-on you meant the Blockly block “inle script (advance)”.

Now of course your first answer is clear to me. Sorry but all the new terms confuse me sometimes.

Thanks, you really made it that I now know what went wrong and I also understood every step. :+1: :1st_place_medal:

Finally I continued working on my project and realized that this syntax is unfortunately not quite right either.

The correct commands with Using ECMAScript 5.1 are:

itemRegistry.getItem('MemberItem').addGroupName('ParentGroupItem');
itemRegistry.getItem('MemberItem').removeGroupName('ParentGroupItem');

itemRegistry.getItem('MemberItem').addMember(itemRegistry.getitem('ParentGroupItem'));
itemRegistry.getItem('MemberItem').removeMember(itemRegistry.getitem('ParentGroupItem'));