Extending Blockly with new openHAB commands

isBefore is what will most closely match how it works in all the other rule languages. I find it to be more self documenting as well. But I don’t have a firm opinion on that. Either way should work.

Maybe. There are times where one has a DT string they need to parse. However, the number of ways a DT can be represented is huge and I would probably limit it to just supporting ISO8601 strings. If the users need more flexibility than that they will have to use raw code. Otherwise you need to get in the business of providing formatting strings and stuff like that, which would be awesome in the long run but I’m not yet sure worth the effort right now.

I don’t know that we need to support all of ZDT, but at a minimum we would need to support the add/minus methods. isBefore and isAfter we’ve already discussed and you basically have working. I’m of two minds as to whether we should expose epoch or not. I like to encourage people to use Duration instead but that’s a whole other set of blocks with a bunch of operations too.

But of course as soon as it’s there people will want to control how it’s displayed or logged so we might need to support formatting too.

I think so since it’s a cross cutting feature and requirement. They are needed for all those Actions as well as to be used in their own right.

Thanks for the input.

The only thing I don’t like when I prototyped this when I try to translate “<=” as it would become “is before or equal” which doesn’t sound so nice.

One other thing I just noticed:

How could me make the block more clear that is a date comparison block - I used the blueish logic block color - I could instead use the zdt color. Adding the label “date” wouldn’t look nice, I think.

The effort is minimal. If it makes sense I would add that and I would just support one format. I think it is good enough for most of the cases.

Ok, that resonates with me. Though I would love to here @ysc opinion on that as well. It won’t break anything but it will appear differently (I also need to find a way how to document that in the blockly reference then)

I’ll have a look into that after having finished the check.

“Is before or the same as” would work, I think? “Equals” is a bit mathsy, which may be confusing when it comes to dates!

Given the nature of timestamps, unless the two operands are literally the same variable, they will never be equal. The Java ZonedDateTime has a resolution down to the nanosecond. It’s almost impossible to generate two separate timestamps that are the same at that resolution. That’s why ZonedDateTime doesn’t really even mess with equals.

So I would say, don’t bother with <= nor >=. == will only return true if the two timestamps are really the same variable. To actually compare two different timestamps for equality, you need to do it in a fuzzy way. Decide on a resolution, for example, equal within a second or equal within 100 milliseconds.

I think it should be the blueish logic color. It’s a logic block so I think that’s most appropriate.

In Stefan’s example he’s comparing dates though - this would be equal timestamps for the same date, wouldn’t it?

1 Like

We currently have this one already

image

How about adding a more generic one like so?

2 Likes

If you just have a date and no time then a LocalDate should probably be used. I don’t know what is backing the “date” block but my original comments and concerns had to do with ZonedDateTimes (and LocalDateTimes if we are being thorough).

Yes, making that more generic would work, but we would still need to support now.

These are all backed by ZonedDateTimes from day one which I am hesitant to change not to break anything.

I would have to add an additional one because otherwise it would break the rules that use the now-related one.

Hello together,

thank you very much for your effort to extend Blockly for OH.
I was planning to use Blockly for my rules and scripts exclusively. Due to the lack of some functionality I started to write my own Blockly libraries in OH.

I would like to compare to dates, The date-block generates a ZonedDateTime with the fields for time set to 0. Every time i want to check a specific time against another ZonedDateTime I have to alter the time fields returned from the date block with a custom block. This is functional but results in a huge block.

The FieldDatePicker is a nice way to select a date. I think a similar or combined one for the time-component of ZonedDateTime would be useful.

Is it possible to instantiate the FieldDatePicker with yaml and get the selected value to a block defined in a custom Blockly library?

1 Like

Apparently not - because you have to feed it the f7 object instance, which you cannot do in YAML. I’ll try to find a solution.

In OH 3.2

I’m doing a script (actually Groovy) which is called from a UI rule. But there’s not much help on that and if I figure the blockly code I can normally work back to Groovy.

So, I’m having problems getting the mqtt binding UI to send json output right so I thought I’d do it in my script. However, I can’t see how to find a link to the action to do the publish.

Previosly I’ve done this;

def mqttActions = getActions("mqtt","mqtt:broker:mqttbroker")
mqttActions.publishMQTT("sensors/garage/command/door1", "STATUS")

but when I do that in the rule i get;

2022-01-11 15:43:37.760 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ec4c7f85d1' failed: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.getActions() is applicable for argument types: (String, String) values: [mqtt, mqtt:broker:mqttbroker]
Possible solutions: getFactory()

How do I get this with my script?

And more generally. I found I have access to a variable called triggeringItem which I can use in the Groovy script, but I only stumbled across it working because I’ve used in other scripting. Is there a definative list of all the things in scope which I have access to while executing my Groovy script from within a UI rule?

See JSR223 Scripting | openHAB

That shows almost everything that exists in your rule be default. For your first question you’ll notice actions which is access to the ThingActions class. That’s what getActions() really exists on. Rules DSL hides a lot of that sort of thing from you.

def mqttActions = actions.getActions("mqtt", ...

What isn’t in those docs is the event Object which also gets passed into your rule. This contains information about the event that caused the rule to run. See Event Object Attributes — openHAB Helper Libraries documentation for the most comprehensive docs I know of for what event will contain under what circumstances.

There is no equivalent to triggeringItem but there is event.itemName. You can get the state from items[event.itemName] (or what ever the syntax for working with a Map in Groovy is). You can get the actual Item using ir.getItem(event.itemName).

It might be the case that you also get the same implicit variable as Rules DSL rules get. If so see Rules | openHAB.

  1. I thought that too, but there is not getActions on it.
2022-01-11 16:44:42.180 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ec4c7f85d1' failed: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: org.openhab.core.automation.module.script.internal.defaultscope.ScriptThingActions.getAction() is applicable for argument types: (String, String) values: [mqtt, mqtt:broker:mqttbroker]

Not sure what I’m meant to do the ScriptThingActions? to get to something I can call publish on.

  1. That list of things is scope was useful. I think it’s just missing triggeringItem from the list. It’s only defined when called from a ‘member of’ rule. But I think it should be in the list, as useful.

Got it!

it’s differently named…

def qttActions = actions.get(“mqtt”,“mqtt:broker:mqtt_broker”)

Then all I can say is that Groovy works differently somehow and you’ll have to figure it out on your own. I can’t help with that. In Nashorn JS and Jython which are both JSR223, what I wrote is how to get at the Thing Actions.

I’m not sure what ScriptThingActions are either. I can’t find that in the OH JavaDocs. It might be a private data member class or something.

Glad you got it. I should have looked up an example before just going from memory.

Typically in JSR223 the standard way is to use event since it’s more complete and explicit and doesn’t depend on “magic” the way that Rules DSL rules do. In other environments like JS Scripting or jRuby the Rules DSL implicit variables do not exist at all.

Note, that list of things that is in scope is the default preset. It’s what gets exposed in the rule by default no matter what. triggeringItem, triggeringItemName, newState, etc. are implicit variables that depend on how the rule was triggered. They are not part of the default preset. They are like the method arguments passed to the rule when it’s triggered. These do not belong as part of that table.

@rossko57 , thanks for explaining. a little clearer now. I might change my code to use event, just to keep it more in line with practice.

Thank you guys for the fantastic work done on Blockly: I’ve migrated so far 90% of my rules and I really enjoy this addition!

I was just wondering if there is already in place a better way to have more than 2 “and/or” conditions than this:

no big deal, but it’s not pretty :slight_smile:

You could put the inputs of one or more blocks on new lines instead of inline. Like so:

Or you could use variables to hold some of the partial results

1 Like

Sometimes I use that option to make the script more “readable”, but I was referring more to the possibility of adding an option in the block itself to select the number of “and” needed in that block.
Something like we have in the “list” block, where you can select the number of items/lines needed

1 Like

@stefan.hoehn: Are there any news on this topic or is it possible to access the event variable? I can not declare a variable in blockly to event.

Thanks for your work!