Skip to content

Commit 44de299

Browse files
committed
sched.py: Add Event-based option.
1 parent 24ec5da commit 44de299

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

v3/as_drivers/sched/sched.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ async def long_sleep(t): # Sleep with no bounds. Immediate return if t < 0.
3131
while times is None or times > 0:
3232
tw = fcron(round(time())) # Time to wait (s)
3333
await long_sleep(tw)
34-
res = launch(func, args)
34+
if isinstance(func, asyncio.Event):
35+
func.set()
36+
else:
37+
res = launch(func, args)
3538
if times is not None:
3639
times -= 1
3740
await asyncio.sleep_ms(1200) # ensure we're into next second

v3/docs/SCHEDULE.md

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ be specified to run forever, once only or a fixed number of times. `schedule`
9696
is an asynchronous function.
9797

9898
Positional args:
99-
1. `func` The callable (callback or coroutine) to run.
99+
1. `func` The callable (callback or coroutine) to run. Alternatively an
100+
`Event` may be passed (see below).
100101
2. Any further positional args are passed to the callable.
101102

102103
Keyword-only args. Args 1..6 are
@@ -154,6 +155,30 @@ try:
154155
finally:
155156
_ = asyncio.new_event_loop()
156157
```
158+
The event-based interface can be simpler than using callables:
159+
```python
160+
import uasyncio as asyncio
161+
from sched.sched import schedule
162+
from time import localtime
163+
164+
async def main():
165+
print("Asynchronous test running...")
166+
evt = asyncio.Event()
167+
asyncio.create_task(schedule(evt, hrs=10, mins=range(0, 60, 4)))
168+
while True:
169+
await evt.wait() # Multiple tasks may wait on an Event
170+
evt.clear() # It must be cleared.
171+
yr, mo, md, h, m, s, wd = localtime()[:7]
172+
print(f"Event {h:02d}:{m:02d}:{s:02d} on {md:02d}/{mo:02d}/{yr}")
173+
174+
try:
175+
asyncio.run(main())
176+
finally:
177+
_ = asyncio.new_event_loop()
178+
```
179+
See [tutorial](https://github.com/peterhinch/micropython-async/blob/master/v3/docs/TUTORIAL.md#32-event).
180+
Also [this doc](https://github.com/peterhinch/micropython-async/blob/master/v3/docs/EVENTS.md)
181+
for a discussion of event-based programming.
157182

158183
##### [Top](./SCHEDULE.md#0-contents)
159184

@@ -262,9 +287,10 @@ This is the core of the scheduler. Users of `uasyncio` do not need to concern
262287
themseleves with it. It is documented for those wishing to modify the code and
263288
for those wanting to perform scheduling in synchronous code.
264289

265-
It is a closure whose creation accepts a time specification for future events.
266-
Each subsequent call is passed the current time and returns the number of
267-
seconds to wait for the next event to occur.
290+
It is a closure whose creation accepts a time specification for future
291+
triggers. When called it is passed a time value in seconds since the epoch. It
292+
returns the number of seconds to wait for the next trigger to occur. It stores
293+
no state.
268294

269295
It takes the following keyword-only args. A flexible set of data types are
270296
accepted namely [time specifiers](./SCHEDULE.md#41-time-specifiers). Valid
@@ -404,14 +430,14 @@ def wait_for(**kwargs):
404430
now = round(time())
405431
scron = cron(**kwargs) # Cron instance for search.
406432
while tim < now: # Find first event in sequence
407-
tim += scron(tim) + 2
408-
twait = tim - now - 600
433+
# Defensive. scron should never return 0, but if it did the loop would never quit
434+
tim += max(scron(tim), 1)
435+
twait = tim - now - 2 # Wait until 2 secs before first trigger
409436
if twait > 0:
410437
sleep(twait)
411-
tcron = cron(**kwargs)
412438
while True:
413439
now = round(time())
414-
tw = tcron(now)
440+
tw = scron(now)
415441
sleep(tw + 2)
416442
```
417443

0 commit comments

Comments
 (0)