OH3 jython, access rule instance

Hi all,

I have this jython rule file:

"""
this class manage lights
"""
from core.rules import rule
from core.triggers import ItemStateChangeTrigger, when
from core import utils
from core import osgi
from core.jsr223.scope import events
from core.actions import ScriptExecution
from java.time import ZonedDateTime

@rule(name="Timered Lights")
class TimerLight(object):
    def __init__(self):
        self.relays_map = {
            'timer1_i': ['timer1_r', 5],
            'LC71A_antibagno_i': ['LC71A_antibagno_r', 10]
        }
        self.triggers = [ItemStateChangeTrigger(item_name=key).trigger for key in self.relays_map.keys()]
        self.timers = {key: None for key in self.relays_map.keys()}
        self.log.info("Timer init done")

    def timer_start(self, switch_name):
        timer = self.timers[switch_name]
        interval = ZonedDateTime.now().plusSeconds(self.relays_map[switch_name][1])
        relay_item = utils.validate_item(self.relays_map[switch_name][0])
        self.log.info("Timing switch {}, timer: {}".format(switch_name, timer))
        if timer is None:
            self.timers[switch_name] = ScriptExecution.createTimer(interval, lambda: events.sendCommand(relay_item, "OFF"))
        else:
            timer.reschedule(interval)
            self.log.info("Exec time: {}".format(timer.getExecutionTime()))

    def execute(self, module, inputs):
        switch_name = inputs['event'].getItemName()
        timer = self.timers[switch_name]
        relay_item = utils.validate_item(self.relays_map[switch_name][0])
        if relay_item is not None:
            current_state = relay_item.getState().toString()
            if current_state == "OFF":
                events.sendCommand(relay_item, "ON")
                self.timer_start(switch_name)
            elif current_state == "ON":
                events.sendCommand(relay_item, "OFF")
                if timer is not None:
                    timer.cancel()

@rule(name="Sensored Lights")
class SensoredLight(object):
    def __init__(self):
        self.triggers = [
            ItemStateChangeTrigger(item_name='timer2_i').trigger
        ]

    def execute(self, module, inputs):
        ruleUID = [rule for rule in rules.getAll() if rule.name == "Timered Lights"][0].UID
        ruleEngine = osgi.get_service("org.openhab.core.automation.RuleManager")
        self.log.info(dir(ruleEngine))

I would like to access timer object (eventually by a method) present in TimerLight instance from SensoredLight instance.

I tried to explore osgi packages without success and also tried a very inefficient way with gc.get_objects() but is not implemented in Jython.

Any suggestions?

Thanks a lot.

In general rules cannot see each other. While you define the class, you don’t actually instantiate that class. The decorator does that and registers the rule with openHAB’s rule registry so you never actually see the Object that represents the rule (it’s not a Python Object anyway so probably wouldn’t be of much use to you).

If you want to share data between rules you have to declare them outside the rules. Or you need to use the new sharedCache if you are on the latest 3.4 milestones (or when you upgrade to OH 3.4). JSR223 Scripting | openHAB

Note that this is new and not supported by the Jython Helper Library. Given the uncertainty of the Jython add-on there’s no guarantee that it will be added to the library.

1 Like

Thanks for your reply.

I thought it was an instance because i saw that init method is called only when rule is loaded and attribute modify during execution persist.

I found this workaround:

tl_class = None
@rule(name="Timered Lights")
class TimerLight(object):
    def __init__(self):
        global tl_class
        tl_class = self

@rule(name="Sensored Lights")
class SensoredLight(object):
    def __init__(self):
        self.triggers = [
            ItemStateChangeTrigger(item_name='timer2_i').trigger
        ]
        self.log.info("Sensored light init done")

    def execute(self, module, inputs):
        global tl_class
        self.log.info(dir(tl_class))

and seems that i can access rule attribute via global variable.

I’ve never liked global variables but I’ll get over it :slight_smile:

Thanks again.