Framework
How the framework works
Using tasko (now called CircuitPyton Async) a set of tasks read from a config file are run at set intervals. This means while a certain task is waiting for a response from something like the radio, other tasks are run.
A state machine is also defined in the config file. Each state has its own set of tasks to run (and their coresponding intervals). All the details for transitions are handled by the state machine.
One can also define exit and enter functions for each state.
State Machine
Tasko
- tasko.add_task(awaitable_task, priority)
Add a concurrent task (known as a coroutine, implemented as a generator in CircuitPython) Use:
scheduler.add_task( my_async_method() )
- Parameters
awaitable_task – The coroutine to be concurrently driven to completion.
- tasko.run_later(seconds_to_delay, awaitable_task, priority)
Add a concurrent task, delayed by some seconds. Use:
tasko.run_later( seconds_to_delay=1.2, my_async_method() )
- Parameters
seconds_to_delay – How long until the task should be kicked off?
awaitable_task – The coroutine to be concurrently driven to completion.
- tasko.schedule(hz: float, coroutine_function, priority, *args, **kwargs)
Describe how often a method should be called.
Your event loop will call this coroutine on the hz schedule. Only up to 1 instance of your method will be alive at a time.
This will use sleep() internally when there’s nothing to do and scheduled, waiting functions consume no cpu so you should feel pretty good about using scheduled async functions.
- usage:
- async def main_loop:
await your_code()
scheduled_task = get_loop().schedule(hz=100, coroutine_function=main_loop) get_loop().run()
- Parameters
hz – How many times per second should the function run?
coroutine_function – the async def function you want invoked on your schedule
event_loop – An event loop that can .sleep() and .add_task. Like BudgetEventLoop.
- tasko.schedule_later(hz: float, coroutine_function, priority, *args, **kwargs)
Like schedule, but invokes the coroutine_function after the first hz interval.
See schedule api for parameters.
- async tasko.sleep(seconds)
From within a coroutine, this suspends your call stack for some amount of time.
NOTE: Always await this! You will have a bad time if you do not.
- Parameters
seconds – Floating point; will wait at least this long to call your task again.
- tasko.suspend()
For making library functions that suspend and then resume later on some condition E.g., a scope manager for SPI
To use this you will stash the resumer somewhere to call from another coroutine, AND you will await suspender to pause this stack at the spot you choose.
:returns (async_suspender, resumer)
- tasko.run()
- Use:
- async def application_loop():
pass
- def run():
main_loop = Loop() loop.schedule(100, application_loop) loop.run()
- if __name__ == ‘__main__’:
run()
The crucial StopIteration exception signifies the end of a coroutine in CircuitPython. Other Exceptions that reach the runner break out, stopping your app and showing a stack trace.