How to Setup Jython

Excellent!

Have you looked through here? You’re using the openhab package, which I never really used, so you may notice a difference in the examples. Just preference. But you were probably having trouble with type conversions.

Compare yours to this and see if what I’ve done makes sense. I used a dictionary to hold/return the payloads, and consolidated the other two rules into one. I also used format (I really like format!) in your logging. Format can convert pretty much anything into a string, and is the best way to concatenate strings. I’m not suggesting to change what you have (if it works, it works!), but hopefully what I’m showing will help you and others with your rules.

from openhab.rules import rule
from openhab.triggers import when
from org.slf4j import Logger, LoggerFactory
from org.eclipse.smarthome.model.script.actions.HTTP import sendHttpPutRequest
import openhab
log = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.Rules")
url = "http://172.16.0.15/api/GBL1Hvu8d4kbK7G1iCb3BtsRQiPXFabP9RpKnjng/groups/10/action"

def setPayload(state):
    global payload
    payloadMap = { "Morning": '{"scene":"Roet3VxODPYz4eG"}',
                   "Day"    : '{"scene":"6ln5CRxZMhip1eo"}',
                   "Evening": '{"scene":"8I4bGQ6kMYV48MH"}',
                   "Night"  : '{"scene":"Off"}'
    }
    payload = payloadMap[str(state)]

setPayload(items["TimeofDay"]

@rule("Set Scene")
@when("Item TimeofDay changed")
def setscene(event):
    log.info("Time of Day is [{}]".format(event.itemState))
    setPayload(event.itemState)
    log.info("JSR223: {} light set [{}]".format(event.itemState, payload))d))

@rule("Hallway Light changed")
@when("Item Hallway_Motion changed")
def hallwaylight(event):
    if event.itemState == OnOffType.ON:
        sendHttpPutRequest(url, "application/json", payload)
    elif event.itemState == OnOffType.OFF:
        payload = '{"on": false}'
        sendHttpPutRequest(url, "application/json", payload)
    log.info("JSR223: Hallway Light [{}]".format(event.itemState))

EDIT:
The readme speaks of some magic about the openhab package…

It can also be used as a module for registering global variables that will outlive script reloads.

… that I do not believe it can do. Have you successfully triggered your motion sensor after a script reload and before TimeofDay changing, and not gotten a NameError for payload? I would think you would need to define payload with a value when the script loads. I’ve update my post to include this.

1 Like

Story of success here also! Installed everything per readme and works like a charm. Tested the telegram action:

from org.slf4j import Logger, LoggerFactory
from openhab.rules import rule
from openhab.triggers import when
from openhab.actions import Telegram

scriptExtension.importPreset("RuleSupport")
scriptExtension.importPreset("RuleSimple")

log = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.MyTestRule")

@rule("Test rule")

@when("Item Test received command ON")

def testFunction(event):
    log.info("Test", "The test rule has been executed!")
    Telegram.sendTelegram("MyBot", "Test")

Thanks @5iver for your work. It was quite simple and straightforward to get this up and running.

2 Likes

FYI, when using the decorators, you do not need the presets. They are loaded in the modules.

+1 on finding the openhab.actions module! I’ve updated the Actions example in the readme to include this option.

1 Like

It seems to me that my rules are firing twice. Is that a known issue?

What version of OH? There was a very recent fix that I made to ItemStateChangedTrigger that could be affecting you. The fix is in the latest snapshot.

Scott, would it make sense to (is or is it possible) to use a decorator to have logging the same between the Rules DSL and Python? I think it would make switching easier.

Also maybe keeping the triggeringItem schema would be helpful for new users?

There is a openhab.log module that I haven’t really looked into, but I plan to. But a simple solution for the way I do logging, is to just do this.

from org.slf4j import Logger, LoggerFactory
logDebug = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.Rules").debug

logDebug("JSR223: Test")

That one is trickier. It would be a breaking change if done in ESH, that would probably not be accepted. I could also change it in the rules module, but it is still a breaking change that others may have an issue with. The other objects being returned are also nicely consistent, and putting in previousState and receivedCommand could make it confusing. IMO, this is just a change in the new rule engine that people will need to learn and accept. I’ll add the following info to the docs (I think it is complete…):

[Table removed so I don’t have to update it in two places. Follow the link above.]

Strange timing… I had just updated the readme this morning with this sort of info… but nowhere near as detailed as this!

1 Like

That is really really useful info!
Im on the latest Milestone. I think 2.4M5. Which is almost a month old anyway. Okay so i will watch it and wait for the next Milestone to be released.

1 Like

I just made some test how to simplify logging. Under /lib/python/local I created empty __init__py and logging.py with this content:

from org.slf4j import Logger, LoggerFactory

log = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.TestLogger")

def logInfo(message):
    log.info(message)

Now in my rule file I just need to import that module and use logInfo():

from openhab.rules import rule
from openhab.triggers import when
from local.logging import logInfo

@rule("TestRule")
@when("Item Test changed")
@when("0/15 * * * * ?")

def execute(event):
    if event is None:
        trigger = "Cron"
    else:
        trigger = event.itemName

    string = "Hello"
    logInfo("Message: \"{}\" triggered by: \"{}\"".format(string, trigger))

Output of script:

2018-10-25 10:36:00.003 [DEBUG] [omation.core.internal.RuleEngineImpl] - The trigger 'Cron-execute-9c74774fd82811e89ba3890da93d9b17' of rule '0502cc98-ddac-4e4f-bb7b-ca732fdca45f' is triggered.

2018-10-25 10:36:00.004 [INFO ] [ipse.smarthome.model.script.TestLogger] - Message: "Hello" triggered by: "Cron"

2018-10-25 10:36:00.004 [DEBUG] [omation.core.internal.RuleEngineImpl] - The rule '0502cc98-ddac-4e4f-bb7b-ca732fdca45f' is executed.

==> /var/log/openhab2/events.log <==

2018-10-25 10:36:03.616 [ome.event.ItemCommandEvent] - Item 'Test' received command ON

2018-10-25 10:36:03.618 [vent.ItemStateChangedEvent] - Test changed from OFF to ON

==> /var/log/openhab2/openhab.log <==

2018-10-25 10:36:03.619 [DEBUG] [omation.core.internal.RuleEngineImpl] - The trigger 'Item-Test-changed' of rule '0502cc98-ddac-4e4f-bb7b-ca732fdca45f' is triggered.

2018-10-25 10:36:03.620 [INFO ] [ipse.smarthome.model.script.TestLogger] - Message: "Hello" triggered by: "Test"

2018-10-25 10:36:03.620 [DEBUG] [omation.core.internal.RuleEngineImpl] - The rule '0502cc98-ddac-4e4f-bb7b-ca732fdca45f' is executed.

Hopefully I’m not inventing the wheel again :smile:
@5iver how would I go and make this import statement automatic so in my environment I would not need separate import in every rule file but just straight out use logInfo()?

1 Like

FYi: Updated to the newly released Milesone 5 Build. Seems like the double executions of the scripts is gone ! SO all good now

2 Likes

Few question about moving from the OH2.3 directory structure to the new structure.

  1. From repository, the contents of Core, ie the automation folder, goes in to the openHABconf folder, replacing the existing automation directory.
  2. Previous personal scripts that were in the automation/JSR232 folder now go into automation\lib\python\personal.
  3. For personal modules, ie not scripts, where should we put these?
  4. For modules that we want to share/add to the community, where do these go?
  5. For scripts that we want to share/add to the community, where do these go?

Mike

Hi, Michael (@mjcumming) Rather than duplicate the documentation @5iver generated, take a look at the Getting-Started page on github:

https://github.com/OH-Jython-Scripters/openhab2-jython/blob/master/Docs/Getting-Started.md#file-locations

Hi Scott, its after reading the instructions that I am asking… kinda highlights the difficulties writing documentation - what seems obvious/intuitive to one is confusion to another :slight_smile:

Understood, I’ve certainly encountered that issue numerous times before and will again, I’m sure.

For my current setup, I duplicated the directory layout exactly as shown at the link I provided (Actually, /etc/openhab2/automation is a symlink to the “real” location of the automation directory on my system, /usr/share/openhab2/automation.)

Actually, if the files in question are standalone scripts, e.g., rule scripts and not library module components, the proposed location is under automation\jsr232\personal\. For personal library components, the proposed location is automation\lib\python\personal\.

The proposed directory for such modules/components is under automation\lib\python\community\. Similarly, for scripts that you would like to share with the community, put them under automation\jsr223\community\.

1 Like

I wasn’t aware that git doesn’t allow empty directories. I have these in my remote, but they do not sync. I’ve now added a README.md to them, so the /automation/jsr223/community/ and /automation/jsr223/personal/ directories show up. Hopefully this helps!

Put a .gitignore file into the currently empty directories. I’m not certain, but I think .gitignore can be empty.

1 Like

That was the first solution I was looking at, but using the readme (with a helpful description) seemed like a better option!

Sounds like a better approach to me.

I finally made the migration from 2.3 to 2.4 - working well so far.

I wonder if we should close this thread as much of the info is related to 2.3?

Found the issue, the correct import is

from core.jsr223.scope import events

I am having trouble importing events into a module.

from core.osgi import events 

but events.postUpdate does not work.

AttributeError: 'module' object has no attribute 'postUpdate'

Am I doing the import correctly?