[SOLVED] Instance alive after reload of rule.py file

I hope I can illustrate a problem that drove me nuts this afternoon.

I have a universal rule definition that just instantiates a helper object in a library module which gets parametrized by a JSON definition. This helper object also deliveries the trigger definition, which it compiles out of the JSON. It also processes the triggers coming in.

This is a try to convert my current huge DSL rule controlling my 100+ lights (see my Tutorial/Example)

During the tests, I had weird behaviors, which I could not explain, it was haunting.

The reason I realized behind this that when I edited the py files and reloaded all the initiated timers kept running in the background from the zombie instances. The only solution for me was to restart OH.

Is there anything that would guarantee that the instantiated classed and attached times would go away?

from core.log import logging, LOG_PREFIX
from core.rules import rule
import imp
import personal.LightControlLib
imp.reload(personal.LightControlLib)
from personal.LightControlLib import lightManager
 
log = logging.getLogger(LOG_PREFIX + ".this.is.my.log")    
 
LIGHT_SETTINGS= '''
{
    "testGU10L":
        {
            "ONOF" : 1,
            "MIDI" : 7,
            "ITLI" : "testGU10L",
            "ITIL" : "HallwayDownMotion",
            "ITMO" : "HallwayDownMotion"
        },
    "testGU10M":
        {
            "ONOF" : 0,
            "MIDI" : 7,
            "ITLI" : "testGU10M",
            "ITIL" : "HallwayDownMotion",
            "ITMO" : "HallwayDownMotion"
        }
}
'''

LIGHT_TRIGGERS='''
{
    "testGU10L":
        {
                "TOG" : [
                    ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "2002"],
                ],
               "DIM" : [
                    ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "2001"],
                ],
               "MOV" : [
                    ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "2004"],
                ]
        },
    "testGU10M":
        {
                "TOG" : [
                    ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "1002"]
                ],
               "DIM" : [
                     ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "1001"]
                ],
               "MOV" : [
                    ["deconz:switch:d6dfbf93:ccccccfffe51c077011000:buttoneven", "1004"]
                ]
        }
}
'''

@rule("Light Manager Rule", description="This is an rule for controlling lights")   
class LightManagerRule(object):    
    lights = lightManager(LIGHT_SETTINGS, LIGHT_TRIGGERS)
    def __init__(self):
        
        self.triggers = self.lights.getAllTriggers()    

    def execute(self, module, inputs):     
        self.lights.execute(module, inputs)                            
      

If using the Helper Libraries, if you define a scriptUnloaded() function in your script file, that function will get called when the file is unloaded. Put code to cancel timers in that function and do any other cleanup that might be required.

Here’s an example from my expire binding replacement:

def scriptUnloaded():
    """ Called at script unload, cancel all the latent timers. """
    for key in timers:
        timers[key].cancel()
2 Likes

There are two special functions that scripted automation (nothing to do with the helper libraries) checks to see if they exist in your script when it loads (scriptLoaded) and unloads (scriptUnloaded). You can use the latter to clean up after your script, such as cancelling timers. There is an example in the documentation (and another for scriptLoaded), but I have an update coming with a little more detail.

In case you haven’t seen this yet, you may want to take a look through this example, since it is very similar to what you have implemented in your DSL rule…

1 Like

I moved the utility class out of the rule class and implemented a clean up timer method on the utility class, which I call out of scriptUnloaded.
That does the magic, waiting for the next wall to hit.

thanks to @rlkoshak and @5iver

lightsMgr = lightManager(LIGHT_SETTINGS, LIGHT_TRIGGERS)


@rule("Light Manager Rule", description="This is an rule for controlling lights")   
class LightManagerRule(object):    
    def __init__(self):
        
        self.triggers = lightsMgr.getAllTriggers()    

    def execute(self, module, inputs):     
        lightsMgr.execute(module, inputs)        

def scriptUnloaded():
    log.info("************* Unload ********* ")        
    lightsMgr.cleanUpTimer()          

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.