I’m getting my head around timers using Jython. Some time back @5iver recommended I use the ScriptExecution.createTimer method, rather than the native Jython threading.Timer. Naturally, therefore, I’ve started my experiments by using threading.Timer…
Goal
- Dim lights over a long period of time…
- Using a re-useable python function that can be called from within a ‘normal’ rule…
- With a timer…
- And be able to cancel the dimming at any time.
I can do 1, 2 and 3. I’m kind of stuck on 4.
Method
Here’s what I currently have (abridged) that addresses goals 1, 2, 3 and 4 (sort of):
From within a rule, I call the function toggle_dimming
. Into the function I pass the name of the Item that I want to dim, and the length of time over which dimming should occur.
import personal.personal_functions
reload(personal.personal_functions)
from personal.personal_functions import toggle_dimming
...
toggle_dimming(dimmer_item_name, t)
My file personal_functions
includes the following:
from core.jsr223.scope import ir
from core.jsr223.scope import events
from threading import Timer
...
#Initialise a timer
dimming_timer = None
...
def toggle_dimming(item_name, interval):
global dimming_timer
if dimming_timer is None:
#if timer is None:
start_dimming(item_name, interval)
else:
stop_dimming()
...
def start_dimming(item_name, interval):
#Grab current dimming level
current_dimmer_level = int(str(ir.getItem(item_name).state))
global dimming_timer
if current_dimmer_level is not 0:
#Adjust dimmer
events.sendCommand(ir.getItem(item_name), str(current_dimmer_level-1))
#Start timer
dimming_timer = Timer(interval, start_dimming, [item_name, interval])
dimming_timer.start()
...
def stop_dimming():
global dimming_timer
if dimming_timer is not None and dimming_timer.isAlive():
dimming_timer.cancel()
dimming_timer = None
This is all great. It’s not particularly robust, but I can start and stop the dimming process.
However, I have to lights that I want to dim, independently, using this same python function. Currently, the timer is attached to the global variable dimming_timer
, which means I can’t start a second dimming process without interfering with the first (I think).
What I’d like to do is create a timer handle back in the rules file, which I then pass through to toggle_dimming
as an argument. The toggle_dimming
function would then use this argument to check whether the timer exists or not.
- If it doesn’t, continue on to
start_dimming
, passing the handle through once more as an argument.start_dimming
would then use that handle for the timer itself. - If it does, continue on to
stop_dimming
, passing the handle through once more as an argument to enable stopping of the timer.
I’ve tried creating a handle in the rules file. I’ve tried importing a handle from the module file (personal_functions
). Neither work - I guess the handle only becomes a timer when inside of start_dimming
, and because it’s no longer a global variable, nothing else knows about it, or can access it. Additionally, when creating the timer, I can’t add the handle argument into the lambda because it doesn’t yet exist as a timer object - it will only exist once the timer is created, but then it’s too late to pass an argument to the lambda (or is it?)
So I guess the question is: how can I transfer a timer handle between rules and functions, without using a global variable?
(For completeness, and to put @5iver at ease, I am also experimenting with the ScriptExecution.createTimer method. This topic is more to improve my understanding of the underlying basics, I guess…)