Just to be clear, and because I promised you a GIF:
The days between now and waste on the left is made from the Marketplace (@deibich) block, using the now block from the same library. This creates the code:
var deibich_blockly_ChronoUnit = Java.type('java.time.temporal.ChronoUnit');
var deibich_blockly_ZonedDateTime = Java.type('java.time.ZonedDateTime');
deibich_blockly_ChronoUnit.DAYS.between(deibich_blockly_ZonedDateTime.now(), waste);
The days between now and waste on the right is made from the openHAB (3.3M6) block, using the now block from the same openHAB Dates & Times library. This creates the code:
var chronoUnit = Java.type("java.time.temporal.ChronoUnit");
var zdt = Java.type("java.time.ZonedDateTime");
chronoUnit.DAYS.between((zdt.now()),waste);
Save for the variable names, the code looks identical to me.
The block from the Marketplace is able to be inserted into the comparison block.
The block from openHAB is not able to be inserted into the comparison block
So I’m still not quite sure why it’s not working. Is the Marketplace block identifying as a number, and the openHAB one isn’t?
Before I fixed my block it had the type “datetime” which is not equal to “number” on the right hand side. When I say type this is something that is defined in the code by the developer of the block (which is me). You can define what the output type of that block is and you can define what type is allowed as input for “holes” in a block. The library version is defined as “Number” (i double checked it), mine was mistakenly defined as datetime. The equals block makes sure that the left and the right hole get the same type (the blue “0” is a number type block), so it worked with the library block but not with the core block. This is why it it didn’t match the type in the comparison and it prevented it to connect.
However, I have fixed that and will provide the fix today (note that it needs to be reviewed and merged first before the fixes will become available)
I have a generic Blockly script that runs when a light group is triggered by a motion sensor. It then waits a certain amount of time to turn off the light or in the case of a retrigger of the motion sensor keep the lights on. I’ve tried to do this with the timers available in the OpenHAB section but that doesn’t work properly as timers (or probably the event context) is lost when a different light group is triggered.
I’m now using the common blocks from this community marketplace post: Collection of common blocks. Basically the timer block that keeps the triggering event context. That block actually works great and allows me to create the desired automation.
Is it possible to include the common blocks (or at least the specific timer one that keeps the event context) into the main OpenHAB section? It’s to avoid that I’m dependent on an ‘external’ block instead of what is available in OpenHAB out of the box. Thanks for considering!
As @rlkoshak is our genie on timers I loop him in here:
Rich, the first block is the one that Marco mentions, the second is ours
The code difference is minimal
if (typeof this.timers['MyTimer'] === 'undefined' || this.timers['MyTimer'].hasTerminated()) {
this.timers['MyTimer'] = scriptExecution.createTimerWithArgument(zdt.now().plusSeconds(10),event, function (event) {
})
} else {
this.timers['MyTimer'].reschedule(zdt.now().plusSeconds(10));
}
if (typeof this.timers['MyTimer'] === 'undefined' || this.timers['MyTimer'].hasTerminated()) {
this.timers['MyTimer'] = scriptExecution.createTimer(zdt.now().plusSeconds(10), function () {
})
} else {
this.timers['MyTimer'].reschedule(zdt.now().plusSeconds(10));
}
The only difference is that it uses
createTimerWithArgument
add the event-variable as an additional parameter and forwards it to the function
Could we not just do that in general?
If not, we could give the timer-blocks an additional choice to choose from but I need to check of that would be backward compatible, so it doesn’t break old blocks.
There are subtitles involved here that probably needs to be explored before deciding how to proceed. The big concern is that
sometimes you want to have the event and possibly other stuff as it was when the timer was created
other times you want to have the event and other stuff as it is right now, possibly having been changed since the timer was created on a subsequent rule trigger.
The difference is subtle but important. Ideally both use cases should be supported. I personally prefer using function generators because it lets you “fix” multiple variables rather than just the one variable. For example:
var timerGenerator = (one, two) => {
return function() {
// function called by the timer which uses arguments one and two somehow
}
}
...
scriptExecution.createTimer(zdt.now().plusSeconds(10), timerGenerator(event, foo));
We call a function passing the arguments and get back a function that will get called by the timer. The passed in arguments become fixed and won’t be overridden when the rule runs again. But that’s a pretty big lift for the typical blockly user (though I think it should be possible).
I think maybe splitting the difference would be be better. Rather than forcing the argument passed to the timer to be the event, why not let us pass our own argument, including event? But I think that would involve creating a new “timer with argument” block where one can select the event or any other variable defined.
Has anyone worked with location type items in Blockly? are there any speciality blocks that i could simply import?
I would like to be able to calculate the distance to a moving object (a car) and get a message from openHAB when the object (car) is closer to home than a certain distance.
I created this one for this usecase: Geographic information system - #5 by timl But the “location type” itself is not supported yet. I worked with native float (latitude and longitude).
Hey @joriskofman
I also love blockly… here a much smaller code. You can create a list from the location item and access directly the first (0) and second (1) item:
This for example allows to find out how long a door has been kept open and if it exceeds a certain time, a notification is sent to the user to close it
Note: to be able to use the skip=true, rrd4j isn’t sufficient as it does not support skipping. You may add influxdb for that purpose and set the default persistence to that.
I’d like to have your opinion on the following topic.
Since we have introduced our blocks it more and more became clear to me that the naming of the word “item” in the blocks is actually not really consistent and it can lead to the wrong usage of the blocks
note that I just yesterday implemented some more rigid type checking on these which was actually flawed over the past months but still type checking can be “circumvented” when introducing variables (type checking is then not applied).
So what is the problem - let’s have a look at these blocks:
Again, in 4.0 I have implemented checks, that make sure that the blocks cannot be attached to the wrong place (that is still possible in 3.4) but with vars it can be pretty confusing and to be honest I myself fell intro that trap:
We could try to detect in jsscripting (graalvm) if a name or an item object is given and therefore become more forgiving and resilient. However, that doesn’t improve the current implementation based on Nashorn.
I‘d also like to have your opinion on a Blockly topic.
During the portation of Blockly to JS Scripting, @stefan.hoehn and I found out, that the Date & Time parsing Blocks for Nashorn generate ZonedDateTimes in the UTC time zone (indicated by a Z at the end of the ZonedDateTime‘s string representation).
In JS Scripting, the ISO parsing is using the system‘s time zone, e.g. for me Europe/Berlin, which is +01:00 from UTC.
We now have to discuss how to proceed: Should Blockly stay with using the UTC zone or use the system time zone?
IMO, we should use the system time zone, because:
openHAB DateTime Items also use the local system time zone (I found this out when I retrieved the state of one of my DateTime Items: REST API returned 2022-12- 27T19:59:16.696974+0100
Using UTC can lead to serious problems when comparing with DateTime Items, because they are in the system time zone:
Imagine you want to check whether a DateTime Item is after 13:04. You create a Block, put 13:04 into it (you wouldn‘t think of: which zone am I, which Zone requires the Block, what do I have to input). Your Item has 13:05 as state, but because it is in your time zone +01:00, it is UTC 12:05. So you end up with a check, that says: 13:05 is not after 13:04, because you did not expect that they have different time zones. The check would only work if it was: 13:05 (+01:00) is after 12:04 (UTC).
IMO using UTC as time zone for user inputted times is a bug that breaks comparisons.
I propose to accept the system time zone that is used in JS Scripting‘s ISO parsing, even though the behaviour of some Blocks will be slightly different, e.g. when calculating the hours between a ZonedDateTime in winter and summer, because in Europe we have summer and winter time and the system time zone seems to respect that. But in that case as well, the system time zone IMO is the better solution, as it returns the correct value of hours between those two DateTimes in your zone.
If even you fell into this trap I’m certain it will become a significant issue among others.
I like this as the bare minimum thing to do. One of the strengths of Blockly is it’s self describing. Being explicit here helps with that.
But, what happens if you have the following?
get state of item -> get item -> item name [MyItem]
Does get state of item only support the Item name or can I also pass it the Item Object?
Could it make sense that we only have a get item and adjust the other blocks to always expect an Item Object?
Or the converse, always expect an Item name and the other blocks adjusted to convert to an Item Object?
I’m nervous about both ideas, especially when you start working with Group members.
And this begs the question, why do we have both get state of item and item name in addition to get x of item (which presumably can get both the state and Item name)? Is it because we get the name and state so often that we created a separate block for convenience or is there a deeper reason?
Why would this be limited to graalvm? It seems possible to do with Nashorn too. I like this idea but it will make the underlying code a tiny bit more complicated.
Ignoring the chaos and breaking changes, what if we did away with item name and instead we get the Item Object in that block? Adjust the other blocks to always want an Item Object instead of just the name. We’d need to keep the get item block for cases where an Item’s name is constructed in the code of course.
There’s a third option, change to use LocalDateTime. I’m not pushing that, just mentioning that it could be an option.
I would tend to agree. We need to use what ever gets stored in DateTimeTypes, which I believe uses the system time zone. If we are consistent with that we should have a smoother overall experience.