OperationMode with individual blockly library

Hi all,
I want to show my current solution that I have implemented to have some kind of scenes implemented.
Therefore I use a OperationMode item for each room.
I can set the OperationMode by user input or automatically by another rule.
In this example the light of the guest bathroom is switched on if someone enters the room. Based on the operation mode the light is choosen, for ChillOut and Guest Mode, the cupboard light is switched on. On all other modes, the main light is used. If the no one is in the room anymore, all lights are switched off.

In another room I want to have the motion sensor to not switch the light off on some operation modes,
therefore the Do on leave statement has the operation mode check, too. The ambient light is switched on in another rule that is triggered if the operationmode is set.

uid: blocklibrary_japhias
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Apr 15, 2024, 8:07:44 AM
component: BlockLibrary
config:
  name: japhias Block Library
slots:
  blocks:
    - component: BlockType
      config:
        type: presenceRule
        message0: Presence with brightness limit of %1 in Room %2 Do on entry %3 Do on
          leave %4
        nextStatement: ""
        previousStatement: ""
        args0:
          - type: input_value
            name: brightness
            check: Number
          - type: input_value
            name: presenceItem
          - type: input_statement
            name: executeOn
          - type: input_statement
            name: executeOff
        inputsInline: true
        colour: 90
        tooltip: ""
        helpUrl: ""
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: if(items.getItem(items.getItem({{input:presenceItem}}).name +
                "_Praesenz").state === "ON") {
                if(items.getItem(items.getItem({{input:presenceItem}}).name +
                "_Helligkeit").state >= {{input:brightness}}) {
                {{statements:executeOn}} } } else { {{statements:executeOff}} }
        toolbox:
          - component: PresetInput
            config:
              name: presenceItem
              shadow: true
              type: oh_item
    - component: BlockType
      config:
        type: checkSendCommand
        message0: Check and send Command %1 for Item %2
        nextStatement: ""
        previousStatement: ""
        args0:
          - type: input_value
            name: commandValue
          - type: input_value
            name: targetItem
        inputsInline: true
        colour: 90
        tooltip: ""
        helpUrl: ""
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: log('sendInfo').info("TEST");
                if(items.getItem({{input:targetItem}}).state.toString() !=
                {{input:commandValue}}) {
                items.getItem({{input:targetItem}}).sendCommand({{input:commandValue}})}
        toolbox:
          - component: PresetInput
            config:
              name: targetItem
              shadow: true
              type: oh_item
          - component: PresetInput
            config:
              name: commandValue
              shadow: true
              type: text
    - component: BlockType
      config:
        type: operationMode
        message0: Check Operation Mode of Room %1 contains %2 Do if true %3 Do if false
          %4
        nextStatement: ""
        previousStatement: ""
        args0:
          - type: input_value
            name: room
          - type: input_value
            name: modeList
          - type: input_statement
            name: executeTrue
          - type: input_statement
            name: executeFalse
        inputsInline: true
        colour: 90
        tooltip: ""
        helpUrl: ""
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: if({{input:modeList}}.includes(items.getItem(items.getItem({{input:room}}).name
                + "_OperationMode").state)) { {{statements:executeTrue}} } else
                { {{statements:executeFalse}} }
        toolbox:
          - component: PresetInput
            config:
              name: room
              shadow: true
              type: oh_item
  utilities:
    - component: UtilityJavaType
      config:
        javaClass: org.openhab.io.openhabcloud.NotificationAction
        name: notifications
    - component: UtilityJavaType
      config:
        javaClass: org.openhab.core.model.script.actions.ScriptExecution
        name: scriptExecution

Thanks for posting!

If you publish this to the marketplace, others can install your library through MainUI instead of copy and paste.

For your “check and send command” block you can use items.getItem({{input:targetItem}}..sendCommandIfDifferent({{input:commandValue}}); as a simpler implementation. That’s built into the JS Scripting library and therefore available in Blockly.

Finally, you don’t actually use (nor are they necessary) your utilities. To send a notification just use:

actions.NotificationAction.sendNotification("romeo@montague.org", "Balcony door is open");

To create a Timer use

actions.ScriptExecution.createTimer(time.ZonedDateTime zdt, function functionRef, any param1, /* ... */ paramN);

There’s no need to import the Java classes. But since you are not actually using these utilities anyway you should remove them.

Thanks for the Tips.
Now I would like to add a Block that I can give two items, a group of all lights of the room and additionally one list of Lights that are already part of this group (OK would be possible to get rid of the first Item, If I want)
The Block should switch of all the lights (in the group) but not the explicitly named ones, e.g. to switch the different Lights on and the others off, e.g. If the Operation Mode changes.
Is it needed to use here a do while (going through the group) in combination with an If (checking If Item is named)? Or do you see a smarter solution?

I like to use list operations for stuff like this.

For example, if you had the list of Item names that you don’t want to send the command to in a list:

var excludeItems = [ "Light1", "Light2", "Light3" ];

Then you can filter the members of the Group and then loop through what’s left in a couple lines of code.

items.MyGroup.members.filter( light => !excludeItems.contains(light.name) )
                     .forEach( light => light.sendCommand('ON') );

Yes, I see no other way of looping through the items of the loop and exclude the ones you don’t want. Writing this with standard OH blocks should be straight forward and I would recommend to implement this first with the standard blocks where you can easily debug that and then derive a special purpose block for it. Use get-members-of-group with a foreachitem-inlist block (see the example following that link) and in the foreach-block use an if-block to filter the blocks you don’t want (you could check it against a map that delivers the unwanted items).

I am not sure why you want to implement custom block for that? You could also write a function that you could use several times in the same rule but of course not if you use that often in different rules (then you have to copy that function).