@@ -46,53 +46,63 @@ def launch(func, tup_args):
46
46
loop .create_task (res )
47
47
48
48
49
- class Delay_ms (object ):
49
+ class Delay_ms :
50
+ verbose = False
50
51
def __init__ (self , func = None , args = (), can_alloc = True , duration = 1000 ):
51
52
self .func = func
52
53
self .args = args
53
54
self .can_alloc = can_alloc
54
55
self .duration = duration # Default duration
55
- self .tstop = None # Not running
56
+ self ._tstop = None # Killer not running
57
+ self ._running = False # Timer not running
56
58
self .loop = asyncio .get_event_loop ()
57
59
if not can_alloc :
58
60
self .loop .create_task (self ._run ())
59
61
60
62
async def _run (self ):
61
63
while True :
62
- if self .tstop is None : # Not running
64
+ if not self ._running : # timer not running
63
65
await asyncio .sleep_ms (0 )
64
66
else :
65
- await self .killer ()
67
+ await self ._killer ()
66
68
67
69
def stop (self ):
68
- self .tstop = None
70
+ self ._running = False
71
+ # If uasyncio is ever fixed we should cancel .killer
69
72
70
73
def trigger (self , duration = 0 ): # Update end time
74
+ self ._running = True
71
75
if duration <= 0 :
72
76
duration = self .duration
73
- if self .can_alloc and self .tstop is None : # No killer task is running
74
- self .tstop = time .ticks_add (time .ticks_ms (), duration )
75
- # Start a task which stops the delay after its period has elapsed
76
- self .loop .create_task (self .killer ())
77
- self .tstop = time .ticks_add (time .ticks_ms (), duration )
77
+ tn = time .ticks_add (time .ticks_ms (), duration ) # new end time
78
+ self .verbose and self ._tstop is not None and self ._tstop > tn \
79
+ and print ("Warning: can't reduce Delay_ms time." )
80
+ # Start killer if can allocate and killer is not running
81
+ sk = self .can_alloc and self ._tstop is None
82
+ # The following indicates ._killer is running: it will be
83
+ # started either here or in ._run
84
+ self ._tstop = tn
85
+ if sk : # ._killer stops the delay when its period has elapsed
86
+ self .loop .create_task (self ._killer ())
78
87
79
88
def running (self ):
80
- return self .tstop is not None
89
+ return self ._running
81
90
82
91
__call__ = running
83
92
84
- async def killer (self ):
85
- twait = time .ticks_diff (self .tstop , time .ticks_ms ())
93
+ async def _killer (self ):
94
+ twait = time .ticks_diff (self ._tstop , time .ticks_ms ())
86
95
while twait > 0 : # Must loop here: might be retriggered
87
96
await asyncio .sleep_ms (twait )
88
- if self .tstop is None :
97
+ if self ._tstop is None :
89
98
break # Return if stop() called during wait
90
- twait = time .ticks_diff (self .tstop , time .ticks_ms ())
91
- if self .tstop is not None and self .func is not None :
99
+ twait = time .ticks_diff (self ._tstop , time .ticks_ms ())
100
+ if self ._running and self .func is not None :
92
101
launch (self .func , self .args ) # Timed out: execute callback
93
- self .tstop = None # Not running
102
+ self ._tstop = None # killer not running
103
+ self ._running = False # timer is stopped
94
104
95
- class Switch ( object ) :
105
+ class Switch :
96
106
debounce_ms = 50
97
107
def __init__ (self , pin ):
98
108
self .pin = pin # Should be initialised for input with pullup
@@ -127,7 +137,9 @@ async def switchcheck(self):
127
137
# Ignore further state changes until switch has settled
128
138
await asyncio .sleep_ms (Switch .debounce_ms )
129
139
130
- class Pushbutton (object ):
140
+ # An alternative Pushbutton solution with lower RAM use is available here
141
+ # https://github.com/kevinkk525/pysmartnode/blob/dev/pysmartnode/utils/abutton.py
142
+ class Pushbutton :
131
143
debounce_ms = 50
132
144
long_press_ms = 1000
133
145
double_click_ms = 400
0 commit comments