Jython helper libraries for OH3

Yes this seems to work, thanks!

One last thing which is not working for me regarding Jython rules is executeCommandLine. Did you get this working? I can’t really get any useful info why it is not working. I have changed the parameters as suggested in docs and other posts, but none of them worked. Basically it returns instantly with ‘None’, not even waiting for the timeout.

I was able to solve it. Basically you need to pass every command line argument as a seperate argument for executeCommandLine.

I have reverted the StartupRule trigger for the time being. I don’t quote understand why the old one worked and the new one doesn’t. It seems that the new one should be the one that works.

This works for me:

class StartupTrigger(Trigger):
    """
    This class builds a StartupTrigger Module to be used when creating a Rule.

    See :ref:`Guides/Rules:Extensions` for examples of how to use these extensions.

    Examples:
        .. code-block::

            MyRule.triggers = [StartupTrigger().trigger]

    Args:
        trigger_name (string): (optional) name of this trigger

    Attributes:
        trigger (Trigger): Trigger object to be added to a Rule
    """
    def __init__(self, trigger_name=None):
        trigger_name = validate_uid(trigger_name)
        self.trigger = TriggerBuilder.create().withId(trigger_name).withTypeUID("jsr223.StartupTrigger").withConfiguration(Configuration()).build()

This seems like it should work instead, but it doesn’t

class StartupTrigger(Trigger):
    """
    This class builds a StartupTrigger Module to be used when creating a Rule.

    See :ref:`Guides/Rules:Extensions` for examples of how to use these extensions.

    Examples:
        .. code-block::

            MyRule.triggers = [StartupTrigger().trigger]

    Args:
        trigger_name (string): (optional) name of this trigger

    Attributes:
        trigger (Trigger): Trigger object to be added to a Rule
    """
    def __init__(self, trigger_name=None):
        trigger_name = validate_uid(trigger_name)
        self.trigger = (
            TriggerBuilder.create()
            .withId(trigger_name)
            .withTypeUID("core.SystemStartlevelTrigger")
            .withConfiguration(Configuration({"startlevel": "100"}))
            .build()
        )

I’m not sure how executeCommandLine would be related to jython, especially the helper libraries, but for the benefit of others who might come across the same issue, could you post your code both before and after?

Yes, I can’t understand this either. But the old one is working for me. Though (I don’t know why) my rules loads much slower on startup. This is not a real issue, now it loads almost as slow as DSL rules do, before on 2.5.x Jython rules loaded instantly…

I think it is related to changes in the core libraries, so this affects all scripting languages (even DSL), that is where I found the solution for Jython as well.

I’m not sure how the old syntax looked like, but it was something like this:

from core.actions import Exec

# Usual Jython helper decorators here @rule, @when, etc...
# The actual commandLine call was something like this:

Exec.executeCommandLine("python3 /etc/openhab/scripts/openhab.py", 10000)

Now you have to do it this way:

from core.actions import Exec

from java.time import Duration

Exec.executeCommandLine(Duration.ofSeconds(100), "python3", "/etc/openhab/scripts/openhab.py")

Notice that you now need to import the Duration class from java.time and the timeout is now in seconds, previously it was in milliseconds.
Also you need to seperate all parameters as a seperate parameter. Previously you could pass the whole command in one string. So basically where you had spaces in your command before, now you need to make it a seperate parameter.

executeCommandLine is part of OpenHAB core, not just jython.

With Duration, you could use .ofMillis, ofMinutes, etc. See Duration (Java Platform SE 8 )

Yeah I know, I used that docs as a reference as well.

I just tried to follow the docs which suggest seconds now, not to cause misunderstading as this thread might help others when migrating their rules…

if I use these imports:

from java.time import ZonedDateTime as DateTime
import java.time.ZonedDateTime as DateTime

and I create a timer like this:

@rule("Turn on Bathroom ceiling light after motion is detected between specific times 6-8", description="Turn on Bathroom ceiling light after motion is detected between specific times 6-8", tags=["Tag 1", "Tag 2"])
@when("Item XiaomiMotionSensorBathroom_Motion changed" or "Item XiaomiMotionSensorUpstairsBathroom_Motion changed")

def XiaomiMotionSensorBathroom_Motion(event):
    if items["ZWaveNode120ZW100Multisensor6SensorLuminance"]  <  DecimalType(44) or items["ZWaveNode049ShutterBathroom_BlindsControl"]  >  DecimalType(30):
       if DateTime().getHour() >= 6 and DateTime().getHour() < 10:
            if items["XiaomiMotionSensorBathroom_Motion"] == ON or items["XiaomiMotionSensorUpstairsBathroom_Motion"] == ON:
                events.sendCommand("BathroomCeiling_Power", "ON")
                ScriptExecution.createTimer(DateTime.now().plusSeconds(240), lambda:(XiaomiMotionSensorBathroom_Motion_3(CLOSED)))

def XiaomiMotionSensorBathroom_Motion_3(event):
    if items["XiaomiMotionSensorBathroom_Motion"] == OFF and items["XiaomiMotionSensorUpstairsBathroom_Motion"] == OFF:
        events.sendCommand("BathroomCeiling_Power", "OFF")
        events.sendCommand("BathroomLEDStrip_Ledcolor", "OFF")
    else: XiaomiMotionSensorBathroom_Motion(ON)

i receive the following error:

2020-12-25 07:26:24.815 [WARN ] [jsr223.jython                       ] - Traceback (most recent call last):
  File "C:\OpenHab\conf\automation\lib\python\core\log.py", line 65, in wrapper
    return function(*args, **kwargs)
  File "C:\OpenHab\conf\automation\lib\python\core\rules.py", line 109, in execute
    self.callback(inputs.get('event'))
  File "<script>", line 32, in XiaomiMotionSensorBathroom_Motion2
TypeError: No visible constructors for class (java.time.ZonedDateTime)

2020-12-25 07:26:24.815 [WARN ] [jsr223.jython                       ] - Traceback (most recent call last):
  File "C:\OpenHab\conf\automation\lib\python\core\log.py", line 65, in wrapper
    return function(*args, **kwargs)
  File "C:\OpenHab\conf\automation\lib\python\core\rules.py", line 109, in execute
    self.callback(inputs.get('event'))
  File "<script>", line 14, in XiaomiMotionSensorBathroom_Motion
TypeError: No visible constructors for class (java.time.ZonedDateTime)

Is that possible to fix this timer, or have a kind of workaround?

Remove this line

It was part of original py and it works and necessary in 2.xx version. Anyway I tried it and it it gives thsi error message:

2020-12-25 16:05:07.818 [WARN ] [jsr223.jython                       ] - Traceback (most recent call last):
  File "C:\OpenHab\conf\automation\lib\python\core\log.py", line 65, in wrapper
    return function(*args, **kwargs)
  File "C:\OpenHab\conf\automation\lib\python\core\rules.py", line 109, in execute
    self.callback(inputs.get('event'))
  File "<script>", line 32, in XiaomiMotionSensorBathroom_Motion2
TypeError: No visible constructors for class (java.time.ZonedDateTime)

2020-12-25 16:05:07.834 [WARN ] [jsr223.jython                       ] - Traceback (most recent call last):
  File "C:\OpenHab\conf\automation\lib\python\core\log.py", line 65, in wrapper
    return function(*args, **kwargs)
  File "C:\OpenHab\conf\automation\lib\python\core\rules.py", line 109, in execute
    self.callback(inputs.get('event'))
  File "<script>", line 14, in XiaomiMotionSensorBathroom_Motion
TypeError: No visible constructors for class (java.time.ZonedDateTime)

I’m sorry, I don’t know why you’re getting this error. It seems unrelated to the jython helper libraries, so you should try posting it as a separate topic.

1 Like

Probably. I had same issue with prevoius version and Scott had solved it. Problem is with line:

ScriptExecution.createTimer(DateTime.now().plusSeconds(240), lambda:(XiaomiMotionSensorBathroom_Motion_3(CLOSED)))

Either syntax of ScriptExecution or with createTimer function. Solution was to change the syntax last time. I’ll do some search as well and if I find solution I’ll publish. createTimer is a commonly used expression.

So problem was the syntax. This version is working now, ff somebody wants to use more sensor value with lambda:

from core.rules import rule
from core.triggers import when
from core.actions import ScriptExecution
from java.time import ZonedDateTime as DateTime

@rule("Turn on Bathroom ceiling light after motion is detected between specific times 6-8", description="Turn on Bathroom ceiling light after motion is detected between specific times 6-8", tags=["Tag 1", "Tag 2"])
@when("Item XiaomiMotionSensorBathroom_Motion changed" or "Item XiaomiMotionSensorUpstairsBathroom_Motion changed")

def XiaomiMotionSensorBathroom_Motion(event):
    if items["ZWaveNode120ZW100Multisensor6SensorLuminance"]  <  DecimalType(44) or items["ZWaveNode049ShutterBathroom_BlindsControl"]  >  DecimalType(30):
        if DateTime.now().getHour() >= 6 and DateTime.now().getHour() < 15:
            if items["XiaomiMotionSensorBathroom_Motion"] == ON or items["XiaomiMotionSensorUpstairsBathroom_Motion"] == ON:
                events.sendCommand("BathroomCeiling_Power", "ON")
                ScriptExecution.createTimer(DateTime.now().plusSeconds(120), lambda: (XiaomiMotionSensorBathroom_Motion_3(CLOSED)))

def XiaomiMotionSensorBathroom_Motion_3(event):
    if items["XiaomiMotionSensorBathroom_Motion"] == OFF and items["XiaomiMotionSensorUpstairsBathroom_Motion"] == OFF:
        events.sendCommand("BathroomCeiling_Power", "OFF")
        events.sendCommand("BathroomLEDStrip_Ledcolor", "OFF")
    else: XiaomiMotionSensorBathroom_Motion(ON)

Hello to all and good evening,

After migrating and setting up jython in OH3 I keep getting this entry in the logs at every start-up:

2021-01-29 22:26:37.804 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.805 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.806 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.811 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.819 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.821 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.821 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.824 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.824 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.828 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.828 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available
2021-01-29 22:26:37.832 [INFO ] [ab.core.service.AbstractWatchService] - ScriptEngine for py not available

Could someone help me how to get this sorted?

Thanks for all your help.

Best regards

You can ignore those if your scripts are running. It seems to be a message on startup before jython is loaded.

@JimT Thank you very much for your fast reply.

I found an issue on github regarding this issue:

Best regards.

1 Like

Hello
When trying my DWD storm rule
to switch, I tried to do this through the import
from java.time import ZonedDateTime as DateTime
to master.
But if I get an error message, he can’t do anything with from
Please help.

That was the query in Openhab 2.5.11
var String jsonString = sendHttpGetRequest (“https://www.dwd.de/DWD/warnung/warnapp/json/warnings.json”)
var String newString = transform (“JS”, “Wetter_DWD_getWarningsJSON.js”, jsonString)
logInfo (“Warning”, “On”)
if (newString! = “NULL”)
{
var String newStart = transform (“JSONPATH”, “$ .start”, newString)
var DateTime timestart = new DateTime (Long :: parseLong (newStart))
Warning_start.postUpdate (new DateTimeType (timestart.toString))
var String newEnd = transform (“JSONPATH”, “$ .end”, newString)
}

@Malti1812 this looks like you are using JavaScript or a JavaScript Transformation, please open a new topic for that. Also please use code fences when posting code.

My problem is only in DateTime timestart
and DateTime timeend which was called earlier from joda