Blockly 4.1/4.2
When we released openHAB 4.0 a lot of new functionality was introduced in Blockly which we described in the blog in July 2023 but we haven’t been lazy in the past two releases which is why I thought I’ll summarise that for everyone who loves Blockly as much as I do. In some cases I also want to go deeper to explain the details.
It goes without saying that all this wouldn’t have been possible without my dear openHAB friend @florian-h05 and also @jimtng.
If you only want to know how to use one specific feature, go to the latest Blockly Reference which can be found here as the docs have already been updated.
Table of content
- Blockly Upgrade
- Blockly Style Selection
- Typed Variables
- Adjust persistence blocks to breaking changes
- HTTP block
- Thing Extensions
- Timer Context Extension
- Math Extensions
- Logic Extensions
- Multiline Edit Fix
Let’s get started…
Blockly Upgrade
Thanks to @jimtng Blockly has been upgraded from v9.2.0 to v10.4.2 which didn’t directly bring some real fancy stuff for you as a user but is something I didn’t dare to do (openHAB 4.0 did a major Blockly version increase though). Therefore I am really thankful that Jim approached it as it provides the latest platform to build Blockly!
Version 11 is already around the corner since one week or so. All of these changes introduce major changes in the core, so it requires careful upgrades not break anything for the openHAB community. This is why we not only upgraded it but tested each and every block if it was still working. Again, Kudos to Jim for doing that!
Add Blockly Style Selection
Blockly comes in different “design flavors” and again this is something that @jimtng added to our Blockly implementation which is not so obvious in the first place and is why I want to mention it here.
This allows you to select a different block style:
geras
is the standard renderer for openHAB
thrasos
is a bit more tighter and the labels are more centered (see the “if” compared to geras). It is supposed to be a more modern take on the legacy geras renderer.
zelos
emulates Scratch-style and MakeCode-style rendering.
Show Labels
Even though this was introduced already in 4.0 many people overlook another choice in the bottom bar:
It allows to toggle between the ID or the label of the item which is really usefully and again worth mentioning. A small video embedded in the Pull Request Description shows an example for that.
Adjust persistence blocks to breaking changes
Future States
I normally hate to break things and in this case Blockly didn’t actually break something but openHAB changed something in the core that allows persistence also access future values in time series like in a weather report. This led to a rename of internal methods which requires Blockly to generate different code.
So in case you have used historic data with persistence and you migrate from 4.0/4.1 to 4.2 you need to migrate your blockly code which is as ease as opening the rule that contains a persistence block with historic data and then just save it. That’s all.
Of course this comes with the advantage to access future states via Blockly from now on:
For more information on that see Overview on Persistence Blocks.
Previous state value as number
Something that was also added is to get the state directly as a number:
Typed Variables
The most important change was just released very lately and is about variables that can have a type.
Basically this is something I was looking for since at least a year and I therefore would call it a “deal breaker” and the biggest improvement for a very long time.
Until then Blockly only provided untyped variables. Even though this seems to be more straight forward and provides the flexibility to put any type into that variable, it creates some challenges to openHAB Blockly to generate the right code.
Most blocks in Blockly have input and output types defined which allows the editor to check whether one particular block can be used as an input for a different block. This becomes challenging with the standard untyped variables because the type of these is basically -unknown- which means that the Blockly editor is not able to check whether this block is allowed or not to be added at that particular position.
This even more is a challenge when blockly tries to generate the right code. The way it works in Blockly is that the code generation looks at the type of the blocks. Some of the blocks allow to attach different types for example to represent an item. This could be a Text-Block but it could be an Item-Name block or even an Item-Object:
Depending of the type of the block, Blockly knows what code needs to be generated (in this case the third one is different):
console.info(‘CoffeePlug_power’);
console.info(‘CoffeePlug_power’);
console.info(items.getItem(‘CoffeePlug_power’));
Or to give another example:
In this case in the first line it “knows” the “get label of item” blockly expects not only an item-name block as provided in the second line but the get-item-block which returns the item object from which the label can be retrieved. As it detects the item-name-block only it “wraps” it with the "missing get-item-block (in terms of generated code) which in the end results into the same code without the Blockly user knowing it:
console.info(items.getItem(‘CoffeePlug_power’).label);
console.info(items.getItem(‘CoffeePlug_power’).label);
However, the problem arises when such a block will be assigned to a variable because a variable does not “know” about a type during code generation and therefore wrong code would be generated which will fail:
itemVar = ‘CoffeePlug_power’;
console.info(itemVar.label);
Therefore, a new “typed variable” section was introduced:
From now on always prefer Typed Variables over normal Variables!
When you create a variable, you can give the variable a type:
then use that typed variable
and magically Blockly it will create the right code:
myItemNameVar = ‘CoffeePlug_power’;
console.info(items.getItem(myItemNameVar).label);
I am sure that this will improve a lot in the future and avoid a lot of trouble. Just make sure use typed variables whenever you can.
Thing extensions
The Thing block happened to be a rather limited one and was missing the possibility to retrieve information about a thing and it wasn’t possible to iterate over the openHAB Things. This all has now become available and particular with the typed variables it is now very convenient to use:
Side note: I am aware that “for each item → thing” doesn’t really sound nice but it is a sad coincidence that the standard blockly for-block uses the word “item” which might be confusing but can’t easily changed without completely re-implementing the standard for-block.
Timer Context extensions
This is probably another one of my favorites because I noticed during my own implementations that this was a feature I was really missing. It is about providing a context to the statement block of a timer.
What if you wanted to provide some context to the statement block that is run in the future by that timer? That hasn’t been possible in the past or even worse if you tried to use a variable from outside the block it would have led to a wrong result. Due to an extension in the jsscripting that @florian-h05 had provided I was able to provide this in Blockly as well.
From 4.2 on the timer block provides a new input called “with context”.
Timers provide a statement block where the blocks reside that are run when the timer triggers. The context allows data to be provided which is later used when the statements are triggered by the timer (note that in many cases you can just leave the context empty or provide an undefined block).
To provide a context put any block to the context input like shown below, which can be a block of any type like String, Number, a variable or even a Dictionary which could hold several values via a key/value mapping.
The context can then be used within the timer statement block by utilising the “timer context” block:
Here are a few examples that show how this all can be used
The loop is in particular interesting to look at:
- The loop counts from 1 to 10 (actually to 9).
- It therefore creates 5 timers where the first is triggered after 1 seconds, the second after 3 seconds and so on.
- Each timer’s name is based on that counter index, i.e. the first timer’s name is LoopCreatedTimer1 and the last timer is named LoopCreatedTimer9.
- The timer name is then provided to the timer block itself via the context which could then be used in various ways (here it just prints it out).
Here is an example, provided by @rlkoshak below, that shows how to access the Dictionary’s values provided as the context:
More details can be found at Timer Context.
HTTP block
I knew for a long time that a block was missing to allow making HTTP requests from within blockly but I wanted to do it right. This means I wanted to make it as convenient as possible but at the same time not overload it with features when they are not needed. If you look closely on the different methods like GET, PUT, POST, DELETE they differ on what is needed but I didn’t want to create different blocks for each of these. Therefore I came up with a design that “mutates” the block depending on what you chose.
Additionally I added toggles that allow you to hide or show input parameters. This allows to keep the block as small as possible if these parameters are not needed:
Originally the “with Headers” input section is hidden but when you press (H) it will be shown which keeps the block small unless you need to provide them:
Pressing the (T) toggle allows you to define a timeout:
You can find a more detailed explanation on the HTTP-Block here.
I am aware that there are a few things that have been already asked to be implemented, so likely I will add them in the future which is
- URL encoding and
- provide request parameters via a Dictionary.
Provide more Math operations and comparison
Math Operations
Even though not the biggest improvement over all it turned out that some math operations were desperately missing, so I added them. Even more the new blocks “understand” openHAB types like Quantity, so you can use them with Quantity together with Math operation.
Min / Max
The following is a new min/max block that didn’t exist in the original math. It is actually pretty useful as it supports Quantities as well from now on:
Parse Number
A new toNumber block was added in the Math section that parses to float:
Logic Extensions
Undefined
An Undefined block was added as [discussed in this thread](Adds the undefined block as discussed at Blockly: Proposal to change contextual info blocks) which allows to check if for example a variable has a non-defined value:
Multiline edit fix
I won’t list all fixes that went into 4.1/4.2 but one is particular interesting:
Something that at least annoyed me for a long time was the issue that the multiline text field that is in particular used in the “inline script” block was broken in Blockly.
I had the chance to meet a Blockly Developer from Google in Belgium at FOSDEM conference and mentioned the topic to him. Chris actually had already worked on that issue before but it was somehow still appearing on our side and not completely solved. After some iterations with the Google Blockly team though we were finally be able to successfully fix that issue.
I am sure I have a forgotton a few things here and there but overall this should be it. Enjoy the new Blockly extensions. Let me know which of these you like most and where you would want to see new features coming.