Muse Timelines and how to .stop() them
I'm running into an issue where sometimes, for whatever reason, a timeline in Muse will continue past when I .stop() it. For context, I'm using a timeline that "ticks" once a minute, and runs until i kill it:
roomTimer = gvars.context.services.get("timeline")
roomTimer.start([60000],True,-1) # Runs until killed
roomTimer.expired.listen(minuteTick)
During my room shutdown script, i do:
roomTimer.stop()
but I noticed that sometimes the minuteTick is still being called even after the room is "shutdown". Here is my problem: I cant figure out a way to kill a given timer from the tlEvent it sends the function call that triggers it.
Any suggestions? Is there some nuclear option to kill all timelines? Is there someway to trigger the controller to restart the program if i get into this state? Or am i simply using timelines wrong?
Comments
Basically I would say the TL handling is ok... only confusing me is the "gvars"
What firmware of the MU?
Could you post a sample code?
We have deployed the latest firmware for Muse available on amx.com (1.3.34).
My apologies for not explaining gvars. I've broken my code up over a few different files, and I'm using a python file called gvars.py as "global variable" storage.
I can try to post an example code base, but I don't know what really else it would show than what I've posted above.
When I get a button press for room startup, I initialize the timer as so:
roomTimer = context.services.get("timeline")
roomTimer.start([60000],True,-1) # Runs until killed
roomTimer.expired.listen(minuteTick)
in minuteTick I'm simply incrementing a variable and checking to see if its greater than or equal to another variable to time how long the system has been turned on.
during shutdown I'm stopping roomTimer with:
roomTimer.stop()
In bench testing, this works as intended unless I really hammer on it (20-30 startup and shutdown cycles in a row) and in the field its only showing up after about a week or so of room use (8-15 startups/shutdowns a workday, 5 days a week). What I start to see seems like multiple timers running since minuteTick will get called multiple times in a minute and still run when the room is shutdown and I've tried to .stop() the timer. Since (As far as i can tell) there's no way to get the timeline object in the tlEvent parameters, I don't know how to .stop() the instance of the timer that's errant.
Our fix currently is rebooting the controllers once a week, but I just wanted to see what other options are out there.
I stumbled across something odd today while trying a solution for this problem. It seems like you can register multiple .expired.listen() triggers to the same timeline with the same callback function. As an example:
I'm initializing my timer:
roomTimer = context.services.get("timeline") roomTimer.start([60000],True,0) # Runs Once roomTimer.expired.listen(minuteTick) def minuteTick(tlEvent): context.log.info("minuteTick") # timer restart roomTimer.start([60000],True,0) # Runs Once roomTimer.expired.listen(minuteTick)Every time minuteTick now fires, an additional callback (via roomTimer.expired.listen(minuteTick)) is registered and fires next time minuteTick is called.
I can see pros and cons to this, and if its intended behavior I can work around it. It would be great to have a way in code to make sure a timeline instance is completely gone and all .expired.listen() callbacks are de-registered, since now I cant really confirm if i have multiple timers running or if one timer has multiple .expired.listen()'s registreted to it.
For now, I'm going to try letting the timer only run once and .start() it again during my "tick" handler to keep it from overrunning and double counting.