Extending Blockly with new openHAB commands

Yes I noticed too but don’t have an explanation. Maybe blocks with mutations simply cannot be put as shadow blocks, or maybe it’s possible to hide the mutation “cog” button so the shadow block is an empty dictionary that you can’t change unless by dragging a real block. Otherwise I’m not hostile to the idea of making it a real block, it’s contrary to the “norm” but at least it would work.

What about something like

if (typeof this.timers['MyTimer'] === 'undefined' || this.timers['MyTimers'].hasTerminated()) {
...

I suspect the rationale was also to avoid keeping references to terminated timer instances indefinitely in memory causing them to never be GC’ed, but I’m not sure either setting them to undefined would do that.
And there’s also the logic flaw that the “timer has terminated” block
image
which generates code like

typeof this.timers['MyTimer'] !== 'undefined' && this.timers['MyTimer'].hasTerminated();

is pretty much useless: it would never return true - either the timer is not set, or pending, or running, or has effectively terminated and thus unset again.

I’m not sure either. One would have to look at the scheduler itself to see how well it cleans up after itself.

That would certainly be a little more fool proof I think. Indeed the the timers would never be GC’d but I can’t imagine one would have so many stale timers hanging about where that would make a difference. My assumption is that the scheduler that handles the timers would be smart enough to clean up terminated timers so it should only be the reference in the rule that would keep it from being GC’d. But that’s an assumption and not actual knowledge.

Changing to a check like that would let us eliminate the setting of the timer back to undefined automatically at the minor expense of some extra memory usage.

So for this

image

the result would become

// Change LINE 1
1 if (typeof this.timers['MyTimer'] !== 'undefined' && this.timers['MyTimer'].hasTerminated()) {
2 this.timers['MyTimer'] = scriptExecution.createTimer(zdt.now().plusSeconds(5), function () {
3    logger.error('timer triggered');
4    if (typeof this.timers['MyTimer'] !== 'undefined') {
5       this.timers['MyTimer'].reschedule(zdt.now().plusSeconds(5));
6    }
7    // this.timers['MyTimer'] = undefined; <= take out this line
8  })
9 } else {
10  this.timers['MyTimer'].reschedule(zonedDateTime.now().plusSeconds(5));
11}

or simplified

image

the code would be as follows

// change LINE 1
1 if (typeof this.timers['MyTimer'] !== 'undefined' && this.timers['MyTimer'].hasTerminated()) {
2  this.timers['MyTimer'] = scriptExecution.createTimer(zdt.now().plusSeconds(5), function () {
3   logger.error('timer triggered');
4   // this.timers['MyTimer'] = undefined;  // Take this out 
5  })
6 } else {
7 this.timers['MyTimer'].reschedule(zonedDateTime.now().plusSeconds(5));
8 }

Note that I haven’t tried that out yet (but I sure will as soon as you confirm)

I think those will work. Once the timer is created there will always be that Timer. But I think that is probably OK.

The looping timer is a little contrived and would like to see any docs or examples include an if statement to determine whether or not to reschedule inside the timer. That is a more typical use of a looping timer instead of a timer that loops forever. If someone wants that, a cron triggered rule would be a better choice.

No, if the timer is undefined or has terminated - the first code fence in my post above. The above condition will never be satisfied since the timer is defined just below in the if branch.

Apart from that this seems reasonable. We would keep timers indefinitely in this.timers, and the create timer would simply redefine them after they are terminated. The reference to the old timer would be lost and maybe it would be GC’d eventually.
A minor optimization would be to simply reschedule them if they still exist but are terminated (see the remark in Timer (openHAB Core 3.2.0-SNAPSHOT API) - “This can also be called after a timer has terminated, which will result in another execution of the same code.”), but it would lead to more code we can do without.

Doh! I must be tired. Of course it needs to be or. Can’t believe I missed that.

That assumes that the function called by ‘MyTimer’ will always be the same. You couldn’t have an if statement and schedule a different function to be called in different circumstances under the same Timer name.

Of course you can just use a different Timer name in that case but it might force the user to writing more complicated code than they otherwise would have to.

Dummy me - I actually had noticed that or and by copying I did it wrong. I love the 6-eyes-principles - good you are here.

I will try to fix that and add to the already pushed PR. Maybe, Yannick, you are able to review and merge.

Btw, just for the record, I have updated the first post at the very top to reflect the latest version of the blocks of M5.

1 Like

Yes that would be great. I can’t accept any more features but bugfixes are still ok.

you mean make another one? To avoid Git snafus for single-file edits you can use the GitHub edit file feature (Sign in to GitHub · GitHub).
Sign-off in the commit message is still required, get it from a previous commit.

Sorry for the confusion. I hadn’t seen you have merged the PR. Thanks. Will hopefully be only minor things to fix this issue above.
I would create a new PR for that fix.
New features will then come with a new PR and as you mentioned lately I will target them with small PRs.

@stefan.hoehn I ended up doing the PR: Fix Blockly timer code by ghys · Pull Request #1236 · openhab/openhab-webui · GitHub as I saw another issue and I wasn’t sure if I will be available to review yours before the RC1 build. Thanks!

Ok, thanks.

I can confirm it works now as expected. This is how I tested it (for the curious, I used two different trigger items and I distinguish those with the new block that retrieves event information, i.e. in this case the event item’s name):

I saw you working on the new blocklib (Block Libraries - initial implementation (#1225))
which refers in its editor to “https://openhab.org/link/blocklib-tutorial”.
image

I checked the latest openhab-docs if I find something there but couldn’t. Have you written something there already so that I can start learning about it?

The link works now!
It points to:

Thanks for the writeup, it works now.

can you do me a favor and merge this last PR. It is a small extension to allow retrieving rules parameters within a script that was written with blocklies. This concludes the blockly “Run & Process” section.

Here is how it can be used when having provided it via a script call as shown in here

The PR is pretty small and should be straight forward

1 Like

We have now released this major update of openhab blocklies as part of openhab 3.2.0. It now contains almost 50 specialised openHAB blocks. Thanks to all who helped by contributing their ideas, reviews and feedback.

8 Likes

Thank you Stefan for your great work on the blockly blocks.
Are there any plans to integrate binding actions like sending a telegram notification or a push notification through the myopenhab service?
I work with telegram notifications and this is the last point I need to change to the blockly editor.

Thanks a lot for your effort!

Thanks Johannes.

Currently, I haven’t planned this but you may be able to contribute this in a way similar to the new Block library approach like in this example that was done for Twitter

see the Tutorial: How To Write Block Libraries

Check the Blockly section of the Marketplace. A number of these Actions have already been built and published there. And as @stefan.hoehn pointed out, there is a really good tutorial for writing your own.

Actually I had a Telegram library in mind for the initial set but lacked the time. :man_shrugging:

myopenHAB push notifications are in the built-in set under openHAB > Notifications.

It’s I think the only case of a set of built-in blocks that depend on an add-on but it makes sense to make an exception for OH Cloud.

1 Like

Hi Rich

I just noticed that when I retrieve tags or groups from items it does return a

java.util.Collections

Do you by chance know how to convert that into a Javascript list like so?

var list = [‘tag1’, ‘tag2’];