Collection of common blocks

This library is a collection of use-full blocks that either make the code easier to read, reduce complexity of repeating code snippets or is extending functionality of already existing blocks.

Blocks

Copy state from <sourceItem> to <targetItem>

This block will replace the need of send Command(get state of item (sourceItem) to targetItem), will send the sourceItems current state as command to the targetItem with the purpose of having a more easy-to read code block.
image

Toggle <item>

This block will switch an item between ON and OFF state. If the item is already ON, it will send an OFF command. If the item has any other state (e.g. OFF or null) it will send an ON command
image

Send notification <message> with icon <icon> as <severity> to <recipient>

This block will extend the already existing send notification block with the option to also specify an icon and a severity when sending a notification to an individual recipient (the already existing block only supports this for broadcast & log messages).
image

after <duration> <timeUnit> do with <timerName> <scriptAction> and keep triggering event-context

This block is an extension of the already available timer block and will pass the event variable as argument to the timer function, which will allow the timer to access the initial event (as the timer was initially scheduled), even the event has changed afterwards (e.g. the rule is triggered again by a different item). This topic will include a use case.
image

This block is also available with a reschedule / cancel option if retriggered.
image

Format datetime item <item> with <dateTime Format>

This block will use any dateTime item and return the datetime as a string formatted with a custom dateTime format.

image

Changelog

Version 0.2

  • added additional block to format dateTime Item

Version 0.1.1

  • typo in notifications to align with OOTB block
  • updated timer to import scriptExecution & ZonedDateTime

Version 0.1

  • initial release

Resources

uid: commonBlocks
tags:
  - marketplace:131157
props:
  parameters: []
  parameterGroups: []
component: BlockLibrary
config:
  name: Common Blocks
slots:
  blocks:
    - component: BlockType
      config:
        args0:
          - name: sourceItem
            type: input_value
          - name: targetItem
            type: input_value
        colour: 0
        helpUrl: ""
        inputsInline: false
        message0: Copy state from %1 to %2
        nextStatement: ""
        previousStatement: ""
        tooltip: Will copy current state of first item and send as command to second item
        type: copyItemState
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: events.sendCommand({{input:targetItem}}, itemRegistry.getItem({{input:sourceItem}}).getState());
        toolbox:
          - component: PresetInput
            config:
              name: sourceItem
              shadow: true
              type: oh_item
          - component: PresetInput
            config:
              name: targetItem
              shadow: true
              type: oh_item
    - component: BlockType
      config:
        args0:
          - name: notification
            type: input_value
          - name: icon
            type: input_value
          - name: severity
            options:
              - - info
                - info
              - - warning
                - warn
              - - highly important
                - high
            type: field_dropdown
          - default: mail@demo
            name: email
            type: input_value
        colour: 0
        helpUrl: ""
        inputsInline: false
        message0: send notification %1 with icon %2 as %3 to %4
        nextStatement: ""
        previousStatement: ""
        tooltip: Sends a notification via Cloud Connector to one individual recipient including icon and severity
        type: notificationSingleWithIconAndSeverity
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: "{{utility:notifications}}.sendNotification({{input:email}}, {{input:notification}}, {{input:icon}}, '{{field:severity}}');"
        toolbox:
          - component: PresetInput
            config:
              fields:
                TEXT: message
              name: notification
              shadow: true
              type: text
          - component: PresetInput
            config:
              fields:
                TEXT: window
              name: icon
              shadow: true
              type: text
          - component: PresetInput
            config:
              fields:
                TEXT: test@example.org
              name: email
              shadow: true
              type: text
    - component: BlockType
      config:
        args0:
          - check: Number
            name: duration
            type: input_value
          - name: duration_unit
            options:
              - - seconds
                - plusSeconds
              - - minutes
                - plusMinutes
              - - hours
                - plusHours
              - - days
                - plusDays
              - - weeks
                - plusWeeks
              - - months
                - plusMonths
            type: field_dropdown
          - check: String
            name: timer_name
            type: input_value
          - default: mail@demo
            name: timer_statement
            type: input_statement
        colour: 0
        helpUrl: https://openhab-scripters.github.io/openhab-helper-libraries/Guides/Event%20Object%20Attributes.html
        inputsInline: true
        message0: after %1 %2 do with %3 %4 and keep triggering event-context
        nextStatement: ""
        previousStatement: ""
        tooltip: Schedules a new timer and will pass the event variable as argument to the timer, that you can reuse the initial event during timer execution (e.g. event.itemName)
        type: timerWithInitialEvent
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: >
                if (typeof this.timers === 'undefined') {
                  this.timers = [];
                }

                if (typeof this.timers[{{input:timer_name}}] === 'undefined' || this.timers[{{input:timer_name}}].hasTerminated()) {
                  this.timers[{{input:timer_name}}] = {{utility:scriptExecution}}.createTimerWithArgument({{utility:zdt}}.now().{{field:duration_unit}}({{input:duration}}),event, function (event) {
                  
                  {{statements:timer_statement}}
                  
                  })
                }
        toolbox:
          - component: PresetInput
            config:
              fields:
                TEXT: MyTimer
              name: timer_name
              shadow: true
              type: text
          - component: PresetInput
            config:
              fields:
                NUM: 10
              name: duration
              shadow: true
              type: math_number
    - component: BlockType
      config:
        args0:
          - check: Number
            name: duration
            type: input_value
          - name: duration_unit
            options:
              - - seconds
                - plusSeconds
              - - minutes
                - plusMinutes
              - - hours
                - plusHours
              - - days
                - plusDays
              - - weeks
                - plusWeeks
              - - months
                - plusMonths
            type: field_dropdown
          - check: String
            name: timer_name
            type: input_value
          - name: timer_statement
            type: input_statement
          - name: reschedule_option
            options:
              - - reschedule
                - this.timers[{{input:timer_name}}].reschedule(zdt.now().{{field:duration_unit}}({{input:duration}}));
              - - cancel
                - >
                  this.timers[{{input:timer_name}}].cancel();

                  this.timers[{{input:timer_name}}] = undefined;
              - - do nothing
                - //do nothing
            type: field_dropdown
        colour: 0
        helpUrl: https://openhab-scripters.github.io/openhab-helper-libraries/Guides/Event%20Object%20Attributes.html
        inputsInline: true
        message0: after %1 %2 do with %3 %4 %5 if retriggered and keep triggering event-context
        nextStatement: ""
        previousStatement: ""
        tooltip: Schedules a new timer with option to reschedule or cancle and will pass the event variable as argument to the timer, that you can reuse the initial event during timer execution (e.g. event.itemName)
        type: timerWithInitialEventAndOption
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: >
                if (typeof this.timers === 'undefined') {
                  this.timers = [];
                }

                if (typeof this.timers[{{input:timer_name}}] === 'undefined' || this.timers[{{input:timer_name}}].hasTerminated()) {
                  this.timers[{{input:timer_name}}] = {{utility:scriptExecution}}.createTimerWithArgument({{utility:zdt}}.now().{{field:duration_unit}}({{input:duration}}),event, function (event) {
                  
                  {{statements:timer_statement}}
                  
                  })
                } else {
                  {{field:reschedule_option}}
                }
        toolbox:
          - component: PresetInput
            config:
              fields:
                TEXT: MyTimer
              name: timer_name
              shadow: true
              type: text
          - component: PresetInput
            config:
              fields:
                NUM: 10
              name: duration
              shadow: true
              type: math_number
    - component: BlockType
      config:
        args0:
          - name: toggleItem
            type: input_value
        colour: 0
        helpUrl: ""
        inputsInline: false
        message0: Toggle Item %1
        nextStatement: ""
        previousStatement: ""
        tooltip: Will switch an item ON or OFF, depending on current state
        type: toggleItem
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: >
                if (itemRegistry.getItem({{input:toggleItem}}).getState() == 'ON') {
                  events.sendCommand({{input:toggleItem}}, 'OFF');
                } else {
                  events.sendCommand({{input:toggleItem}}, 'ON');
                }
        toolbox:
          - component: PresetInput
            config:
              name: toggleItem
              shadow: true
              type: oh_item
    - component: BlockType
      config:
        args0:
          - name: dateTimeItem
            type: input_value
          - name: dateTimeFormat
            type: input_value
        colour: 0
        helpUrl: ""
        inputsInline: false
        message0: Formate datetime item %1 with %2
        type: formatDateTime
        output: String
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: (itemRegistry.getItem({{input:dateTimeItem}}).getState()).getZonedDateTime().format({{utility:dtf}}.ofPattern({{input:dateTimeFormat}}))
        toolbox:
          - component: PresetInput
            config:
              name: dateTimeItem
              shadow: true
              type: oh_item
          - component: PresetInput
            config:
              fields:
                TEXT: HH:mm
              name: dateTimeFormat
              shadow: true
              type: text
  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
    - component: UtilityJavaType
      config:
        javaClass: java.time.ZonedDateTime
        name: zdt
    - component: UtilityJavaType
      config:
        javaClass: java.time.format.DateTimeFormatter
        name: dtf
7 Likes

Hi @Matze0211 , thanks for contribution! There’s as small typo in “Format(e) datetime”.

Version of common blocks for GraalJS is here

I replaced itemRegistry with items and made changes in block Format datetime item to correct format in Graal JS

1 Like

Hi all,

I can’t get this to work with OpenHAB 4.0.4.
I see the new timer blocks use shared and private cache and I have no idea how to adapt that for the timer blocks with context.
Maybe someone had the same issue and resolved that?
With the above code I have this bug once again (or at least similiar, but it only reschedules once).

I’m traveling and can only look into this in 2 weeks.

In general the createtimerwithargument function still exists as per the documentation

No Problem, enjoy your trip! :slight_smile: And thanks for the link!

I tried myself, but I’m not a developer and I’m just puzzling here :smiley:

As writing it down might help, here is what I tried:

Generated code from the old script
var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');

var zdt = Java.type('java.time.ZonedDateTime');


if (typeof this.timers === 'undefined') {
  this.timers = [];
}
if (typeof this.timers['MyTimer'] === 'undefined' || this.timers['MyTimer'].hasTerminated()) {
  this.timers['MyTimer'] = scriptExecution.createTimerWithArgument(zdt.now().plusSeconds(10),event, function (event) {



  })
}
Generated code from the new timers
if (cache.private.exists('MyTimer') === false || cache.private.get('MyTimer').hasTerminated()) {
  cache.private.put('MyTimer', actions.ScriptExecution.createTimer('MyTimer', time.ZonedDateTime.now().plusSeconds(10), function () {
    }));
};

Code from the rule template:

                if (typeof this.timers === 'undefined') {
                  this.timers = [];
                }

                if (typeof this.timers[{{input:timer_name}}] === 'undefined' || this.timers[{{input:timer_name}}].hasTerminated()) {
                  this.timers[{{input:timer_name}}] = {{utility:scriptExecution}}.createTimerWithArgument({{utility:zdt}}.now().{{field:duration_unit}}({{input:duration}}),event, function (event) {

                  {{statements:timer_statement}}

                  })
                }
My try to adapt, but without any idea how to integrate the selector for private or shared cache

                if (cache.private.exists[{{input:timer_name}}] === false) || cache.private.get[{{input:timer_name}}].hasTerminated()){
                    cache.private.put([{{input:timer_name}}] = {{utility:scriptExecution}}.createTimerWithArgument([{{input:timer_name}}] , ({{utility:zdt}}.now().{{field:duration_unit}}({{input:duration}}),event, function (event) {

                  {{statements:timer_statement}}

                  })
                }

It all is way more complicated than I thought. Seems like I can’t even understand the Tutorial

I tried to setup a library, to get things started, but this doesn't even compile
uid: blocklibrary_test
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Nov 11, 2023, 3:45:48 PM
component: BlockLibrary
config:
  name: Block Library Reschedule with context test
slots:
  blocks:
    - component: BlockType
      config:
        args0:
          - check: Number
            name: duration
            type: input_value
          - name: duration_unit
            options:
              - - seconds
                - plusSeconds
              - - minutes
                - plusMinutes
              - - hours
                - plusHours
              - - days
                - plusDays
              - - weeks
                - plusWeeks
              - - months
                - plusMonths
            type: field_dropdown
          - check: String
            name: timer_name
            type: input_value
          - default: mail@demo
            name: timer_statement
            type: input_statement
        colour: 0
        helpUrl: https://openhab-scripters.github.io/openhab-helper-libraries/Guides/Event%20Object%20Attributes.html
        inputsInline: true
        message0: after %1 %2 do with %3 %4 and keep triggering event-context
        nextStatement: ""
        previousStatement: ""
        tooltip: Schedules a new timer and will pass the event variable as argument to the timer, that you can reuse the initial event during timer execution (e.g. event.itemName)
        type: timerWithInitialEvent
      slots:
        code:
          - component: BlockCodeTemplate
            config:
              template: >
                if (cache.private.exists[{{input:timer_name}}] === false || cache.private.get[{{input:timer_name}}].hasTerminated()){
                    cache.private.put([{{input:timer_name}}] = {{utility:scriptExecution}}.createTimerWithArgument([{{input:timer_name}}] , ({{utility:zdt}}.now().{{field:duration_unit}}({{input:duration}}),event, function (event) {

                  {{statements:timer_statement}}

                  })
                }
        toolbox:
          - component: PresetInput
            config:
              fields:
                TEXT: MyTimer
              name: timer_name
              shadow: true
              type: text
          - component: PresetInput
            config:
              fields:
                NUM: 10
              name: duration
              shadow: true
              type: math_number

I’ll get some good rest and try another day.

Is there any place where I can see the setup from current timers blockly library to start with?
I only found that and it doesn’t look like a blockly library at all to me.

It took a bit longer, but I got it running with the following code:

if (cache.private.exists('timer_name') === false || cache.private.get('timer_name').hasTerminated()) {
  cache.private.put('timer_name', actions.ScriptExecution.createTimerWithArgument('timer_name', time.ZonedDateTime.now().plusSeconds(5),event, function (event) {
  console.info('Timer with Args running');
  console.info(event.itemName);
 }));
};

However as per this post I receive a warning, that the function is deprecated and will be removed, hence I have not yet updated the blockly library.

1 Like