Refer to event in Blockly

When building scripts using Blockly, how can I refer to the item that triggered the rule?

I’m building a rule that will be triggered by motion detection from several cameras. Depending on which camera detected the motion and triggered the rule, the Blockly script are to send a command to a specific item. So the goal is to avoid creating >10 Blockly scripts for each source/destination item and instead build one. When building it by hand I can refer to it using event.itemName but how can I refer to event using the Blockly UI?

For example:

logger.info('IPCamera brightness triggered: ' + event.itemName);

While in Blockly I can only refer to pre-selected item, like this:
image

Thank you!

I am currently developing a lot of extensions for the blocklies and your case was mentioned here by Rich:

It is currently not yet possible but I will provide that as soon as the latest development has been reviewed.

Hi Stefan

That’s awesome! Keep up the good work :smiley:

Looking forward to the release!

One more quick question. In this Blockly script I only want it occur if after a certain time, such as nautic dawn. I have found out, that one can do the following, to check if it’s after nautic dawn with the astro binding using:

.isAfter

( I think )

It seems like this isn’t possible using Blockly or am I wrong?

I am not sure if I understand what you like to do. Can you provide a code example what you want to do based on a DSL rule?

Here’s a complete javascript doing what I wanted. Note the if statement in beginning comparing using zonedDateTime with .isAfter and .isBefore to determine that the current time is between nautic dusk and nautic dawn.

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
var zonedDateTime = Java.type('java.time.ZonedDateTime');
if (typeof this.timers === 'undefined') {
  this.timers =[];
}

referenceOutdoorLamp = ['OutdoorLamp1_Brightness', 'OutdoorLamp2_Brightness'];
referenceCamera = ['Camera1', 'Camera2'];
targetOutdoorLamp = referenceOutdoorLamp[referenceCamera.indexOf(event.itemName)]

//logger.info('IPCamera brightness triggered: ' + event.itemName);
if (zonedDateTime.now().isAfter(items['LocalSun_nauticDusk_StartTime'].getZonedDateTime()) || zonedDateTime.now().isBefore(items['LocalSun_nauticDawn_StartTime'].getZonedDateTime())) {
  if (typeof this.timers['thisTimer'] === 'undefined') {
    var OutdoorLamp_Brightness_preState = itemRegistry.getItem(targetOutdoorLamp).getState();
    events.sendCommand(targetOutdoorLamp, '100');
    this.timers['thisTimer'] = scriptExecution.createTimer(zonedDateTime.now().plusSeconds(10), function () {
      events.sendCommand(targetOutdoorLamp, OutdoorLamp_Brightness_preState);
      this.timers['thisTimer'] = undefined;
    })
  } else {
    this.timers['thisTimer'].reschedule(zonedDateTime.now().plusSeconds(10));
  }
}

I also had to move the following lines from above “if (typeof this.timers[‘thisTimer’] === ‘undefined’) {” to below it, as otherwise these would fire every time the script runs, even if an existing timer is running:

var OutdoorLamp_Brightness_preState = itemRegistry.getItem('OutdoorLamp_Brightness').getState();
events.sendCommand('OutdoorLamp_Brightness', '100');

as one would expect from the following blockly UI element, from which the above code is inspired by:
image

I know by now, this is starting to demand quite a bit from a GUI :grinning_face_with_smiling_eyes:

That clarifies it, thanks

Well, what you are expecting is actually a comparison function that is provides <, > and = which is based on the methods of the ChronoZonedDateTime-Class isAfter, isBefore, isEqual,

Let me see how we can provide that in the future. Currently the new Ephemeris Blocks only provide the ZonedDate(Time) without a Time which is probably not enough.

  • What type of Item do you use here that is able to provide a zoneddatetime here?

What we would need here is that we have to

  • to retrieve something special from an item and not only the state itself and then encapsulate that as a timetype-block
  • and then provide a comparison possibility either by explicitly have a isBefore, isEqual, isAfter or reuse the comparison operator for comparing them but I need to see if that is possible (I kind of doubt that because it uses more operators than what can be implemented easily with that class).

@rlkoshak Any ideas?

not a simple thing to do but most likely doable.

To use the Astro .isAfter() Action you’ll need to access the Actions on the Astro Thing. @stefan.hoehn I think we talked about how to handle calling Binding Actions but I don’t know where we ended up on that. I think we put that off until later since there is no way to query OH through the REST API to get the list of all available Actions. Then you have the problem that all the Actions have unique function definitions so they cannot be statically defined as a block.

It’s a DateTime Item’s state.

Working with date times is always a challenge. You really have more operations than those three. You also have addition and subtraction operations and those can be done for each unit of time (years, hours, etc.).

Those cover the instances in time cases but you also have durations, the amount of time between two instances in time.

Handling all of this stuff is going to involve a lot of work, not so much complex work but a lot of tedious work since there are so many variations.

For a couple of examples:

// DateTime Item's state plus an hour
var hour = items["MyItem"].getZonedDateTime().plusHours(1);

// Number of seconds since a DateTime Item's state and now
var ZDT = Java.type("java.time.ZonedDateTime");
var Duration = Java.type("java.time.Duration");
var delta = Duration.between(items["MyItem"].getZonedDateTime(), ZDT.now());
var secs = delta.getSeconds();

// Now I want the Hours
var hours = delta.getHours();

// Is that Item's DateTime after now?
if(items["MyItem"].getZonedDateTime().isAfter(ZDT.now()){

From a Blockly perspective, I like to keep the words “is before” and such as it’s more consistent than other operations already implemented in Blockly. Abstracting that to the comparison operators I think serves more to obscure than it does to make things more clear.

1 Like

I will add it to my todo-list :slight_smile:

1 Like

Here is the information about the pull request for your requirement: Extending Blockly with new openhab commands - #215 by stefan.hoehn

I hope that this is what you came for :slight_smile:

Stefan