JSR223/Groovy cannot use DecimalType, OpenClosedType and others

Hi there,
I’ve started a migration from openHAB 2.4 (running on macOS) to openHAB 2.5 (running on a rPI 3B+).

The migration went pretty well except for my groovy rules: I cannot access very common types like OpenClosedType or DecimalType (listed https://www.openhab.org/docs/configuration/jsr223.html). Other types like SimpleRule or OnOffType are usable.

The scripts worked when used with openHAB 2.4, I just changed 2 imports from

import org.eclipse.smarthome.automation.*
import org.eclipse.smarthome.automation.module.script.rulesupport.shared.simple.*

to

import org.openhab.core.automation.*
import org.openhab.core.automation.module.script.rulesupport.shared.simple.*

.

Here is a boiled down script version trying to get an Item state as a DecimalType

import org.openhab.core.automation.*
import org.openhab.core.automation.module.script.rulesupport.shared.simple.*
import org.eclipse.smarthome.config.core.Configuration
scriptExtension.importPreset("RuleSupport")
scriptExtension.importPreset("RuleSimple")
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.eclipse.smarthome.core.items.ItemRegistry
//import org.eclipse.smarthome.core.library.types.DecimalType
import org.openhab.core.library.types.DecimalType

//openhab access (otherwise not accessible when used in named classes)
class OH {
    Object events
    ItemRegistry ir

    OH(Object events, ItemRegistry ir) {
        this.events = events
        this.ir = ir
    }
}

class DecTypeTestRule extends SimpleRule {
    String name = "DecTypeTestRule in Groovy"

    private static Logger logger = LoggerFactory.getLogger('DecTypeTestRule')
    private final OH oh

    DecTypeTestRule(OH oh) {
        this.oh = oh
    }

    Object execute(Action module, Map<String, ?> inputs) {
        logger.warn("DecTypeTestRule: executing")
        logger.warn("DecTypeTestRule: getItem: " + oh.ir.getItem('N_AZIMUTH')) //<<< works
        logger.warn("DecTypeTestRule: getItem.state: " + oh.ir.getItem('N_AZIMUTH').state) ////<<< works
        logger.warn("DecTypeTestRule: getStateAs: " + oh.ir.getItem('N_AZIMUTH').getStateAs(DecimalType.class)) //does not work
      // int azimuth   = oh.ir.getItem('N_AZIMUTH').getStateAs(DecimalType.class).intValue() //the intended code
        logger.warn("DecTypeTestRule: done executing")
    }
}

void addTriggers(SimpleRule aRule) {
    List<Trigger> eventTriggers = new ArrayList()
    eventTriggers.add(TriggerBuilder.create()
            .withId("${aRule.class.simpleName}_triggerTest")
            .withTypeUID("core.ItemStateChangeTrigger")
            .withConfiguration(new Configuration([itemName: 'triggerTestRule']))
            .build())
    aRule.setTriggers(eventTriggers)
}

def sRule = new DecTypeTestRule(new OH(events, ir))
addTriggers(sRule)
automationManager.addRule(sRule)

Running this script leads to the following log output:

==> /var/log/openhab2/openhab.log <==
2019-12-29 16:20:05.121 [WARN ] [DecTypeTestRule                     ] - DecTypeTestRule: executing
2019-12-29 16:20:05.125 [WARN ] [DecTypeTestRule                     ] - DecTypeTestRule: getItem: N_AZIMUTH (Type=NumberItem, State=230.87987753820812, Label=Azimuth, Category=null, Groups=[G_ASTRO])
2019-12-29 16:20:05.129 [WARN ] [DecTypeTestRule                     ] - DecTypeTestRule: getItem.state: 230.87987753820812
2019-12-29 16:20:05.133 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule '724b45dc-b4cf-456f-bf71-13dead4ea6db': Fail to execute action: 1

Getting the item seems to be okay (oh.ir.getItem('N_AZIMUTH')), reading its state via state also, but reading its state and converting it to a DecimalType using oh.ir.getItem('N_AZIMUTH').getStateAs(DecimalType.class) is not working.

This ist the item definition

Number   N_AZIMUTH        	              "Azimuth [%.1f]"     				                          (G_ASTRO)	            {channel="astro:sun:home:position#azimuth"}

In another script, I was trying to use OpenClosedType

def ctItem = oh.ir.getItem(ctItemName)
if (ctItem.state == OpenClosedType.CLOSED) {

Running this leads to

2019-12-29 16:03:02.684 [ERROR] [DisplayHallRule                     ] - Error: groovy.lang.MissingPropertyException: No such property: OpenClosedType for class: DisplayHallRule: No such property: OpenClosedType for class: DisplayHallRule

I’ve tried using various import statements but did not find a way to access these types. In special cases, I was able to use strings instead of the problematic types, but that is very dirty.

As you can see by the OH class, I’ve already implemented workarounds for scoping problems related to the named rule class style. Maybe this is also a scoping problem?

Do you have an idea?

Thanks

This was previously reported. There is definitely something wrong with the Groovy’s default script scope. I have an idea of what is happening, but I have not gotten back to this.

There is also this Groovy issue…

Jython is a much better choice for scripted automation.

Interesting, the last comment in your first link indicates I had the same problem when I migrated from 1.8 to 2.4 (and (a) I could not even remember it… and (b) the workarounds are no longer in my rules)

Jython might be much better, but coming from a Java background, Groovy seemed to be the natural choice for me when I started using openHAB 1.8.x several years ago. Since then, I’ve created lots of rules which are extensively unit tested. A full python conversion seems to be time consuming.

My personal opinion: Groovy support in openHAB is essentially broken since 2.0 and it seems there is not enough community activity in order to fix it. It would be fair to warn potential users on the JSR223 page. My rules contain approximately 20-30% of “workaround code”.

Will openHAB deprecate Groovy (i.e. in openHAB 3.0) or is there a committment to Groovy support? I could try to improve Groovy in openHAB or invest my time in learning Python. Although learning Python 2.x (which will soon be EOL) might not be the best investment…

I agree. Groovy is definitely not going to win a popularity contest against Python. I know of two other people besides you that are using Groovy.

Please submit a PR… contributions are appreciated! There is a lot that needs to go into the official documentation about scripted automation.

No. Scripted automation will still be available in OH 3.0, which supports any JVM language that is compatible with the javax.script API. Some languages need some help though and Groovy appears to be one of them. The helper libraries for Jython are much more advanced than the other languages and they make it much easier to write scripts. Nobody has stepped forward to put helper libraries together for Groovy. I still plan to put together a Groovy bundle (and Kotlin, jRuby, etc.) to simplify the installation, once I can get some some agreement about the Jython bundle.

I disagree. There is not much difference between Python 2 and Python 3, mainly due to backporting. This is especially true when it comes to what you’ll need for scripted automation. The print statement, integer division, unicode strings, range(), and exception logging are the differences that come to mind, but these are very easily addressed. The biggest difference is compatibility of Python 3 libraries.

However, Jython has a completely different release schedule than Python 2 and is not going to be EOL any time soon. There is also a Python 3 version of Jython, and at some point we may be able to use graalpython.

Whatever you decide, I’m here to help! At some point, I will get to looking into these issues with Groovy, if nobody has gotten to them already.