How to compare state of string item to a literal value?

Hi, need some help here might be an obvious error but now pulling out my hairs to find out what is the problem.
In my rules I’d like to compare two dates both in string format “yyyy-MM-dd”, however I can’t seem to get it work. Below is my code:

    var String currentDate = new DateTimeType().format("%1$tY-%1$tm-%1$td")
    logInfo("NordPool", "Current date is {}", currentDate)
    logInfo("NordPool", "API date is {}", CurrentApiDate.state)
    if (currentDate == CurrentApiDate.state){
        //The raw data is for today
        logInfo("NordPool", "The raw data is for today")
    }
    else {
        logInfo("NordPool", "The raw data is for tomorrow")    
    }```

Logs:

2022-11-07 11:50:05.774 [INFO ] [g.openhab.core.model.script.NordPool] - Current date is 2022-11-07
2022-11-07 11:50:05.775 [INFO ] [g.openhab.core.model.script.NordPool] - API date is 2022-11-07
2022-11-07 11:50:05.776 [INFO ] [g.openhab.core.model.script.NordPool] - The raw data is for tomorrow```

I have tried to use state.toString and equals method same result. I doubt checked the length of the strings they’re the same. Any suggestion?

Ok I think I found a solution. Apparently “CurrentApiDate.state == currentDate” works - not sure I understand why but this level of ambiguity is very frustrating sometimes :frowning:

It’s not ambiguous in this case.

currentDate is a String. It is only a String and it can only do String type things.

CurrentApiDate is an Item. It can only do Item type things. CurrentApiDate.state is one of the things that an Item can do. That gives you the Item’s current State.

There are lots of different types of State that an Item can carry, depending on the type of the Item. You’ve not explained what type of Item CurrentApiDate is. I’m guessing it’s a StringItem but it could be a DateTimeItem.

A StringItem carries a StringType as it’s State. A StringType and a String are not the same. A StringType is a State and therefore it does State type things, not String type things. However, one of the things that a State can do is toString(). That converts the State to a String.

Once you have a String, you can do String type things with it, like comparing it to another String.

OK, now that we have that out of the way, it helps to understand how Rules DSL works. Unfortunately, it straddles two worlds, the type enforced world of Java and the typeless world of Xtext. It does this by doing it’s best to coerce the two operands of an operation (like ==) to become compatible. And frankly, it sucks at this.

So what exactly is happening in the line currentDate == CurrentApiDate.state? Rules DSL sees the first operand is a String so it calls String.equals(CurrentApiDate.state). Obviously that’s not going to work because String doesn’t know how to do anything with a State.

What’s happening in the line CurrentApiDate.state == currentDate? In this case it sees the first operand is a State and it calls CurrentApiDate.state.equals(currentDate). This works though because the developers of StringType wrote a .equals() function that understands how to compare itself to a String.

Even though it shouldn’t matter, the order of operations matter. You’ll face the same problem with NumberItem and DecimalType.

1 Like

Hi Rich, thank you for the detailed explanations! Sorry I wasn’t aware the StringItem.state is a StringType object instead of String, and it explains why it works this way.
I have some knowledge of Java but still find troubleshooting issue like this very difficult - especially without proper IDE and debug support. Why OH introduces another scripting language instead just let people to write rules in Java/Python?

A decision a decade ago.
For forward comptability, this DSL is going to be around for a while.
If you don’t like it, then don’t use it, but don’t expect everyone else to make the same choice.

And to add just a little detail, as @rossko57 indicates, Rules DSL was added to OH ten years ago. Before that point, OH didn’t have any rules language because it didn’t support that sort of automation.

At that time, there were not as many choices for embedding other programming languages in a Java application (I think they were on Java 1.4 at that time). But, since OH was already using Xtext to define some of the config files (sitemaps, .items files), it was not a big stretch to build a custom rules language using Xtend (which itself is built on Xtext).

For about half of the existence of OH, Rules DSL was the only option for writing rules. Way back in the OH 1.5 days (I think, around the time OH was on Java 1.6 IIRC) a few intrepid users experimented with JSR223 to add Groovy, JavaScript, and Jython support.

In OH 2, a new experimental rules engine was created that supports UI created rules and standardized support for the JSR223 languages. Towards the end of OH 2.5 I believe JRuby was added. This was all on Java 1.8.

In OH 3, the experimental rules engine became just the rules engine. Rules DSL was ported to it. And even more languages have been added for support, including JS Scripting which provides a much more recent version of ECMAScript (11 as opposed to 5) using GraalVM instead of JSR223 (or what ever that interface is called these days) and Blockly was added for graphical legos type programming. There is also an add-on that lets one write rules in Java, but it does not support UI rules.

There has also been support for NodeRed and an external Python 3 rules engine called HABApp since OH 2.? (I don’t remember when these both started to be used).

In the mean time, the original JavaScript support (Nashorn) has been deprecated for some time (it’ll be removed from OH in OH 4 when we move to Java 17 (I think that’s the target, maybe 16) but support will be retained through an add-on. Jython support upstream is not great and it’s still stuck on Python 2.7 with no support for Python 3 in sight.

So that’s a bit of the history and the list of the supported alternatives to Rules DSL.

Thank you @rlkoshak @rossko57 for your reply and good overview!