Can I pass parameter to Timer callback?
Posted: Fri Jan 29, 2021 8:39 pm
How to do that?
Thanks.
Thanks.
Please see the new forum at
https://forum.micropython.org/
Code: Select all
from machine import Timer
my_callback = lambda timer: print(42)
Timer(1).init(mode=Timer.ONE_SHOT, period=1000, callback=my_callback)
Code: Select all
from machine import Timer
def my_callback(timer):
print(42)
Timer(1).init(mode=Timer.ONE_SHOT, period=1000, callback=my_callback)
Code: Select all
from machine import Timer
def timer_partial(func, *args, **kwargs):
# added timer as a mandatory argument
# to filter it out
def inner(timer, *iargs, **ikwargs):
return func(*args, *iargs, **kwargs, **ikwargs)
return inner
Timer(1).init(mode=Timer.ONE_SHOT, period=1000, callback=timer_partial(print, "Hello World", end="=======\n"))
Code: Select all
from machine import Timer
class MyCallback:
def __init__(self, value):
self.value = value
def callback(self, timer):
"""
Callback is called by Timer.
The first argument is the instance of the class
The second argument is the instance of the timer, which is not used here
"""
print("===", self.value, "===")
def __call__(self, timer):
"""
This enables the possibility to call the instance directly.
"""
self.callback(timer)
def __repr__(self):
"""
Method to have a nice representation, but it's not required.
"""
return f"{self.__class__.__name__}(value={self.value})"
my_callback = MyCallback(1337)
# works, because of the __call__ method:
Timer(1).init(mode=Timer.ONE_SHOT, period=1000, callback=my_callback)
# without having the __call__ method:
Timer(1).init(mode=Timer.ONE_SHOT, period=1000, callback=my_callback.callback)
Code: Select all
from time import sleep
from machine import Timer
def partial(func, *args, **kwargs):
def inner(*iargs, **ikwargs):
return func(*args, *iargs, **kwargs, **ikwargs)
return inner
class TimerCallback:
_instances = []
__slots__ = ("_timer", "_callbacks", "_id", "delay", "mode")
def __init__(self, id, delay, mode=Timer.PERIODIC):
if id in self._instances:
raise RuntimeError(f"Timer with id {id} exists already")
self.delay = delay
self.mode = mode
self._id = id
self._callbacks = []
self._timer = Timer(id)
self._instances.append(id)
def _callback(self, timer):
for callback in self._callbacks:
callback()
def start(self):
self._timer.init(mode=self.mode, period=self.delay, callback=self._callback)
def stop(self):
self._timer.deinit()
def add_callback(self, callback, *args, **kwargs):
if not callable(callback):
raise TypeError("Callback must be callable")
prepared_callback = partial(callback, *args, **kwargs)
self._callbacks.append(prepared_callback)
return prepared_callback
def del_callback(self, prepared_callback):
if prepared_callback in self._callbacks:
self._callbacks.remove(prepared_callback)
def kill(self):
self._timer.deinit()
if self._id in self._instances:
self._instances.remove(self._id)
tc = TimerCallback(1, 5000)
tc.add_callback(print, "Hello", "World", sep="\t", end="\n\n\n\n")
my_callback_reference = tc.add_callback(print, "Hello World 2")
tc.start()
sleep(11)
tc.stop()
try:
tc2 = TimerCallback(1, 300)
except RuntimeError as e:
print(e.args[0])
tc.kill()
# will remove also the id
try:
tc2 = TimerCallback(1, 3000)
except RuntimeError as e:
print(e.args[0])
tc2.add_callback(print, "Lesser args")
tc2.start()
sleep(12)
tc2.kill()