Skip to content

Commit

Permalink
Merge pull request #16 from npentrel/eventbus
Browse files Browse the repository at this point in the history
Add eventbus docs
  • Loading branch information
hughrawlinson authored May 18, 2024
2 parents 8837aa3 + 051dcd6 commit efbe04d
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 31 deletions.
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ Hexpansions are accessories that plug into the badge's expansion connectors. Alm

For more information, see:

- [Hexpansion hardware developer guide](hexpansions/index.md).
- [Technical documentation, pinout, and paper and PCB templates][badge-2024-hardware].
- [Hexpansion hardware developer guide](hexpansions/index.md)
- [Technical documentation, pinout, and paper and PCB templates][badge-2024-hardware]

## A reusable platform with an interchangeable part

Expand Down
14 changes: 8 additions & 6 deletions docs/tildagon-apps/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ To test the app, go to the instructions for [simulating your app](./simulate.md)

## The `App` class

!!! quote "Quote by Tom Catshoek"

Apps are just objects with `update()` and `draw()` methods. And optionally async `background_update()`.

To make a badge app in Python, you subclass the [`App` class](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app.py). When you subclass the `App` class to create your app, you need to _overwrite_ some of its methods to make it do something useful.

??? note "Wondering what a subclass is or what _overwrite_ means? Expand this!"
Expand Down Expand Up @@ -124,10 +120,16 @@ To make a badge app in Python, you subclass the [`App` class](https://github.com

### Usage

This section walks you through the most [common usage](#common-usage) first which is enough to build many apps. Afterwards, you'll learn how to [update state while an app is minimized](#update-app-state-while-minimised), how to [draw multiple objects](#draw-multiple-objects), and how to [add asynchronous functionality](#asynchronous-functionality).
This section walks you through the most [common usage](#common-usage) first which is enough to build many apps.

Afterwards, you'll learn how to [update state while an app is minimized](#update-app-state-while-minimised), how to [draw multiple objects](#draw-multiple-objects), and how to [add asynchronous functionality](#asynchronous-functionality).

#### Common Usage

!!! important ""

You can think of the apps on your badge as objects with `update()` and `draw()` methods.

1. To be able to subclass the `App` class, import the `app` package at the top of your Python file:

```python
Expand Down Expand Up @@ -361,7 +363,7 @@ By default, the `background_task()` method is automatically run by the scheduler

| Property | Type | Description |
| -------- | ---- | ----------- |
| `overlays` | Any object with a draw method. | Your app's list of overlays. |
| `overlays` | An array of objects that each have a draw method. | Your app's list of overlays. |

### Methods

Expand Down
9 changes: 2 additions & 7 deletions docs/tildagon-apps/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ Tildagon OS is the name for the firmware that runs on the badge. It is based on

## App Development

!!! warning

This is a work in progress. The badge firmware is not yet ready for general use.

You can write apps for the badge in MicroPython. You can use most MicroPython libraries, and for some functionality we provide
abstractions - for example, you can access all buttons through `events.input`.
You can write apps for the badge in MicroPython. You can use most MicroPython libraries, and for some functionality we provide abstractions - for example, you can access all buttons through [`events.input`](./widgets-and-hardware/badge-hardware.md#buttons).

While developing, you can use your hardware badge for testing your code, or you can use the [simulator].

For more info check out our [Getting Started guide][app-getting-started].
For more info check out [Write a Tildagon OS App][app-getting-started].

## Publishing your app

Expand Down
32 changes: 17 additions & 15 deletions docs/tildagon-apps/widgets-and-hardware/badge-hardware.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,31 @@ You can also use the `ButtonDownEvent` and the `ButtonUpEvent` directly with an

```python
from events.input import Button, BUTTON_TYPES, ButtonDownEvent, ButtonUpEvent
from system.eventbus import eventbus
```

2. Add an event handler in the `__init__` method of your app with the event (`ButtonDownEvent` or `ButtonUpEvent`) and a function that should be called when the event happens:
2. Add a method to handle the event:

```python
def _handle_buttondown(self, event: ButtonDownEvent):
if BUTTON_TYPES["CANCEL"] in event.button:
self._cleanup()
# perform other actions as needed

if BUTTON_TYPES["CONFIRM"] in event.button:
self._cleanup()
# perform other actions as needed
```

3. Add an event handler in the `__init__` method of your app with the event (`ButtonDownEvent` or `ButtonUpEvent`) and a function that should be called when the event happens. Depending on whether the event handler is a synchronoush or asynchronoush method call `on()` or `on_async`:

```python
def __init__(self):
eventbus.on(ButtonDownEvent, self._handle_buttondown, self.app)
# eventbus.on_async(ButtonDownEvent, self._handle_buttondown, self.app)
```

3. Remove the event handler when the app is minimised or closed:
4. Remove the event handler when the app is minimised or closed:

```python
def _cleanup(self):
Expand All @@ -170,17 +185,4 @@ You can also use the `ButtonDownEvent` and the `ButtonUpEvent` directly with an

Make sure you remove the event handler when the app is minimised or closed!

4. Add a function to handle the event:

```python
def _handle_buttondown(self, event: ButtonDownEvent):
if BUTTON_TYPES["CANCEL"] in event.button:
self._cleanup()
# perform other actions as needed

if BUTTON_TYPES["CONFIRM"] in event.button:
self._cleanup()
# perform other actions as needed
```

You can see a more comprehensive example in [`dialog.py`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/dialog.py).
86 changes: 86 additions & 0 deletions docs/tildagon-apps/widgets-and-hardware/eventbus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Eventbus

You can register your events and event handlers with the [`Eventbus`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/system/eventbus.py) package:

## Usage

You can use your own events directly with an event handler that you register on the [`eventbus`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/system/eventbus.py).

1. Import the `system.eventbus` package:

```python
from system.eventbus import eventbus
```

2. Define an event:

```python
class SpecialEvent:
def __init__(self):
pass

def __str__(self):
return "special event"
```

3. Define a synchronous or asynchronous method to be called when the event occurs:

```python
def handle_event(self, event):
# do something
```

```python
async def handle_event_async(self, event):
# do something
```

4. Register your event handler, for example in the `__init__` method of your app with the event and the event handler. Depending on whether the event handler is a synchronous or asynchronous method call `on()` or `on_async()`:

```python
def __init__(self):
eventbus.on(SpecialEvent, self.handle_event, self.app)
```

```python
def __init__(self):
eventbus.on_async(SpecialEvent, self.handle_event_async, self.app)
```

5. Add code to emit the event, for example in your app's `update()` method. Depending on whether the event handler is a synchronous or asynchronous method call `emit()` or `emit_async()`:

```python
def update(self, delta):
# If something happens
eventbus.emit(SpecialEvent())
```

```python
async def update(self, delta):
# If something happens
await eventbus.emit_async(SpecialEvent())
```

6. Remove the event handler when the app is minimised or closed.

```python
eventbus.remove(SpecialEvent, self.handle_event, self.app)
```

!!! caution

Make sure you remove the event handler when the app is minimised or closed!

You can see a more comprehensive example in [`dialog.py`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/app_components/dialog.py) or [`pingpong_app.py`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/firmware_apps/pingpong_app.py).

## Methods

You can use the following methods on the `eventbus`:

| Method | Description | Arguments | Returns |
| ------ | ----------- | --------- | ------- |
| `on(event_type, event_handler, app)` | Register an event for an app alongside the synchronous handler to be called when the event fires. | <ul><li><code>event_type</code>: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.</li><li><code>event_handler</code>: The synchronous function to be called when the event fires to handle the event.</li><li><code>app</code>: The app this event is being registered for.</li></ul> | None |
| `on_async(event_type, event_handler, app)` | Register an event for an app alongside the asynchronous handler to be called when the event fires. | <ul><li><code>event_type</code>: The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`.</li><li><code>event_handler</code>: The asynchronous function to be called when the event fires to handle the event.</li><li><code>app</code>: The app this event is being registered for.</li></ul> | None |
| `emit(event)` | Emit an event to the eventbus. The handler for the event must be synchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
| `emit_async(event)` | Emit an event to the eventbus. The handler for the event must be asynchronous. | `event` : The event, for example `ButtonDownEvent`. An `event` object must have the methods `__init__()` and `__str__()`. | None |
| `remove(event_type, event_handler, app)` | Remove the event for an app from the eventbus. | <ul><li><code>event_type</code>: The event to be removed.</li><li><code>event_handler</code>: The asynchronous function to be called when the event fires to handle the event.</li><li><code>app</code>: The app this event is being removed for.</li></ul> | None |
2 changes: 1 addition & 1 deletion docs/tildagon-apps/widgets-and-hardware/ui-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ The [`Tokens`](https://github.com/emfcamp/badge-2024-software/blob/main/modules/
| Method | Description | Arguments | Returns |
| ------ | ----------- | --------- | ------- |
| `clear_background(ctx)` | Clear the badge background. | `ctx`: context that let's you add graphics or texts. See [`ctx` library](../development.md#the-ctx-library). | None |
| `set_color(ctx, color)` | Set the color for the context. The color must be provided as a string from the following options: `pale_green`, `mid_green`, `dark_green`, `colors.yellow`, `colors.orange`, `colors.pink`, `colors.blue`, `ui_colors.background`, `ui_colors.label`. | - `ctx`: context that let's you add graphics or texts. See [`ctx` library](../development.md#the-ctx-library). | None |
| `set_color(ctx, color)` | Set the color for the context. | <ul><li><code>ctx</code>: context that let's you add graphics or texts. See <a href="../../development#the-ctx-library"><code>ctx</code> library</a>.</li><li><code>color</code>: The provided color as a string from the following options: `pale_green`, `mid_green`, `dark_green`, `colors.yellow`, `colors.orange`, `colors.pink`, `colors.blue`, `ui_colors.background`, `ui_colors.label`. </li></ul> | None |



Expand Down

0 comments on commit efbe04d

Please sign in to comment.