Skip to content

Commit 2564e0b

Browse files
Update docs
1 parent 6f49c74 commit 2564e0b

12 files changed

Lines changed: 290 additions & 8 deletions

docs/apps/appstore.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@
22

33
The MicroPythonOS App Store allows users to download and install new apps to extend system functionality.
44

5-
App discovery is currently done by downloading the app list from [apps.micropythonos.com](https://apps.micropythonos.com).
5+
## Backends
6+
7+
The AppStore app can pull apps from more than one source:
8+
9+
- **BadgeHub.eu** — the community appstore for event badges and community-built apps at [badgehub.eu](https://badgehub.eu). On supported firmware builds this is the default backend. See [BadgeHub Apps](badgehub.md) for details on publishing there.
10+
- **MicroPythonOS Apps** — the curated, manually reviewed app index at [apps.micropythonos.com](https://apps.micropythonos.com).
11+
12+
Use the backend selector in the AppStore UI to switch between sources.
613

714
## Example Apps
815

916
- **Hello World**: A sample app demonstrating basic functionality.
1017
- **Camera**: Captures images and scans QR codes.
1118
- **Image Viewer**: Displays images stored in `/data/images/`.
12-
- **IMU**: Visualize data from the Intertial Measurement Unit, also known as the accellerometer.
19+
- **IMU**: Visualize data from the Inertial Measurement Unit, also known as the accelerometer.
20+
- **Nostr**: A decentralized chat client using the Nostr protocol, shipped as a Python package.
21+
- **Sorter**: A puzzle game where you sort items into the right bins.
22+
- **The Free Lantern Player**: A media player app.
23+
- **Breakout**: A classic brick-breaking game that uses a native C extension module.
1324

1425
## Image Viewer
1526

@@ -34,4 +45,4 @@ The **Image Viewer** app displays images stored in `/data/images/`. See [Support
3445

3546
## Developing Apps
3647

37-
Apps are written in MicroPython and installed in `/apps/`. See [Filesystem Layout](../architecture/filesystem.md) for the app directory structure.
48+
Apps are written in MicroPython and installed in `/apps/`. See [Filesystem Layout](../architecture/filesystem.md) for the app directory structure, [Bundling Apps](bundling-apps.md) for packaging, and [Native C/C++ Apps](native-apps.md) for apps that need compiled extensions.

docs/apps/badgehub.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# BadgeHub.eu Apps
2+
3+
[BadgeHub.eu](https://badgehub.eu) is a community appstore for event badges and MicroPythonOS devices. MicroPythonOS ships with a BadgeHub backend in the AppStore app, so users can browse, install, and update BadgeHub-published apps directly on their device.
4+
5+
## What is BadgeHub?
6+
7+
BadgeHub hosts `.mpk` packages and exposes a JSON API that MicroPythonOS queries for app listings, project details, and downloadable releases. It is particularly useful for:
8+
9+
- conference or camp badge apps
10+
- community-built utilities
11+
- distributing apps without going through the curated MicroPythonOS app index
12+
13+
## Backend endpoints
14+
15+
The BadgeHub backend uses API version 3:
16+
17+
- `https://badgehub.eu/api/v3/project-summaries` — list of all published projects with summary metadata.
18+
- `https://badgehub.eu/api/v3/projects/<slug>` — full project details, including releases, icons, and descriptions.
19+
20+
Each project maps to one MicroPythonOS app package. The project's slug becomes the app identifier in the store.
21+
22+
## Project metadata
23+
24+
A project detail response contains fields such as:
25+
26+
- `name` — display name in the AppStore.
27+
- `description` / `long_description` — short and long descriptions.
28+
- `icon_url` — URL to a 64×64 or larger app icon.
29+
- `publisher` — author or organization.
30+
- `releases` — list of published releases, each with a version and a download URL.
31+
- `main_executable` — optional flag indicating the primary app executable for this project.
32+
33+
The AppManager uses the latest release's download URL to fetch the `.mpk`.
34+
35+
## Releasing an app on BadgeHub
36+
37+
1. Build your `.mpk` following the [Bundling Apps](bundling-apps.md) guide. The top-level folder in the ZIP must match the app's `fullname` exactly.
38+
2. Ensure the archive contains a valid `MANIFEST.JSON`.
39+
3. Upload the `.mpk` to your BadgeHub project.
40+
4. MicroPythonOS will detect the new release the next time the AppStore refreshes the BadgeHub backend.
41+
42+
## Version handling
43+
44+
Releases on BadgeHub should use [semantic versioning](https://semver.org/) strings (for example, `1.2.3`). The AppStore compares the installed version against the latest BadgeHub release and offers an update when the BadgeHub version is newer.
45+
46+
## Switching backends in the AppStore app
47+
48+
The AppStore app can switch between the curated MicroPythonOS backend and the BadgeHub backend. On supported firmware builds, BadgeHub is the default backend. Tap the backend selector in the AppStore UI to switch sources.
49+
50+
## See also
51+
52+
- [Bundling Apps](bundling-apps.md) — creating `.mpk` packages
53+
- [Creating Apps](creating-apps.md) — writing an app from scratch
54+
- [App Lifecycle](app-lifecycle.md)`Activity` and `Service` lifecycle

docs/apps/bundling-apps.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ MicroPythonOS validates this layout while extracting, and rejects packages that
2121

2222
From the parent directory that contains your app folder, create a stored (uncompressed) ZIP that includes the top-level folder. It's recommended to make the `.mpk` deterministic by setting file timestamps to a fixed value, sorting entries, and excluding extra file attributes:
2323

24-
```
24+
```bash
2525
cd internal_filesystem/apps/
2626
find com.micropythonos.helloworld -exec touch -t 202501010000.00 {} \;
2727
(find com.micropythonos.helloworld -type d; find com.micropythonos.helloworld -type f) | sort | TZ=CET zip -X -r -0 /tmp/com.micropythonos.helloworld_0.0.2.mpk -@
@@ -34,8 +34,43 @@ This:
3434
- uses `-X` to exclude extra file attributes
3535
- places `com.micropythonos.helloworld/` as the first entry
3636

37+
## Python packages
38+
39+
An app can also be shipped as a proper Python package. This lets you split an app into many modules, use relative imports, and import shared code cleanly.
40+
41+
To opt in, the app folder must contain an `__init__.py` file, and **every directory on the path to each entrypoint** must also contain an `__init__.py` (or compiled `__init__.mpy`). The AppManager then imports the entrypoint as part of the package. The module name becomes the package fullname dotted with the entrypoint path, for example `com_micropythonos_nostr.chat_list_activity`.
42+
43+
Example `com_micropythonos_nostr` layout:
44+
45+
```
46+
com_micropythonos_nostr/
47+
com_micropythonos_nostr/__init__.py
48+
com_micropythonos_nostr/MANIFEST.JSON
49+
com_micropythonos_nostr/icon_64x64.png
50+
com_micropythonos_nostr/chat_list_activity.py
51+
com_micropythonos_nostr/nostr_service.py
52+
com_micropythonos_nostr/...
53+
```
54+
55+
The `MANIFEST.JSON` still declares `chat_list_activity.py` as the entrypoint; the framework detects the `__init__.py` and loads it as a package automatically.
56+
57+
Relative imports work as usual inside the package:
58+
59+
```python
60+
from . import nostr_service
61+
from .nostr_service import NostrService
62+
```
63+
64+
## Native modules
65+
66+
Apps can include native C/C++ extension modules compiled as MicroPython `.native.mpy` files. Place the compiled `.mpy` in the app folder and import it like a normal module. For build instructions and an example, see [Native C/C++ Apps](native-apps.md).
67+
3768
## AppStore bundling
3869

3970
The apps at https://apps.MicroPythonOS.com are a curated, manually reviewed, vetted collection, often created and maintained by the MicroPythonOS core team.
4071

4172
These are bundled into an [`app_index.json`](https://github.com/MicroPythonOS/apps/blob/main/app_index.json) using [`scripts/bundle_apps.sh`](https://github.com/MicroPythonOS/MicroPythonOS/blob/main/scripts/bundle_apps.sh) and then pushed to the [apps repo](https://github.com/MicroPythonOS/apps).
73+
74+
## BadgeHub.eu publishing
75+
76+
For community and event-badge publishing, MicroPythonOS also supports the [BadgeHub.eu](https://badgehub.eu) appstore backend. See [BadgeHub Apps](badgehub.md) for how to publish an `.mpk` there.

docs/apps/index.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@
33
MicroPythonOS is built around an app-centric model, with built-in apps for core functionality and an App Store for additional apps.
44

55
- [Built-in Apps](built-in-apps.md): Core apps included with the OS.
6-
- [App Store](appstore.md): Download and install new apps.
6+
- [App Store](appstore.md): Download and install new apps, including BadgeHub.eu community apps.
7+
- [Creating Apps](creating-apps.md): Write an app from scratch.
8+
- [App Lifecycle](app-lifecycle.md): Activity and Service lifecycle.
9+
- [Bundling Apps](bundling-apps.md): Package apps as `.mpk` files, including Python packages.
10+
- [Native C/C++ Apps](native-apps.md): Add compiled native modules to an app.
11+
- [BadgeHub Apps](badgehub.md): Publish apps on BadgeHub.eu.

docs/apps/native-apps.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Native C/C++ Apps
2+
3+
Most MicroPythonOS apps are written in MicroPython, but apps can also include native extension modules written in C or C++. These modules are compiled to MicroPython `.native.mpy` files and bundled inside the app's `.mpk` like any other module.
4+
5+
## When to use native code
6+
7+
Use a native module when:
8+
9+
- You need more CPU performance than pure MicroPython can provide (for example, a game loop or signal processing).
10+
- You need to call C libraries that have no MicroPython equivalent.
11+
- You want to reuse existing C/C++ code.
12+
13+
For everything else, prefer plain MicroPython — native modules add build complexity and are architecture-specific.
14+
15+
## How native modules work
16+
17+
MicroPython supports [native machine code modules](https://docs.micropython.org/en/latest/develop/natmod.html) (often called *natmods*). A natmod is a self-contained `.mpy` file that contains compiled machine code and a MicroPython module descriptor. At runtime it is imported just like a `.py` file:
18+
19+
```python
20+
import breakout
21+
breakout.start()
22+
```
23+
24+
MicroPythonOS places the `.mpy` file in the app folder when the `.mpk` is installed. The AppManager's import path then finds it automatically.
25+
26+
## Example: `com.micropythonos.breakout`
27+
28+
The built-in **Breakout** game uses a native C module for the game logic. Its source lives in `c_mpos/breakout/` in the main repository.
29+
30+
Project layout:
31+
32+
```
33+
c_mpos/breakout/
34+
├── Makefile
35+
├── build.sh
36+
└── breakout.c
37+
```
38+
39+
`Makefile`:
40+
41+
```makefile
42+
MPY_DIR = ../../lvgl_micropython/lib/micropython/
43+
44+
MOD = breakout
45+
SRC = breakout.c
46+
LINK_RUNTIME = 1
47+
ARCHES = x64 xtensawin
48+
49+
ifeq ($(ARCH),)
50+
.PHONY: all $(ARCHES)
51+
52+
all: $(ARCHES)
53+
54+
$(ARCHES):
55+
$(MAKE) -f $(lastword $(MAKEFILE_LIST)) ARCH=$@ MOD=$(MOD)_$@
56+
else
57+
include $(MPY_DIR)/py/dynruntime.mk
58+
endif
59+
```
60+
61+
This builds two artifacts:
62+
63+
- `breakout_x64.native.mpy` — for the desktop simulator.
64+
- `breakout_xtensawin.native.mpy` — for ESP32-S3 devices.
65+
66+
The `build.sh` script sets up the Espressif toolchain and then copies the resulting `.mpy` files into the app's folder at `internal_filesystem/apps/com.micropythonos.breakout/`.
67+
68+
## Bundling a native module
69+
70+
1. Write your C/C++ source and a `Makefile` based on the MicroPython `dynruntime.mk` rules.
71+
2. Build the module for every architecture you want to support.
72+
3. Rename or place the output `.mpy` file in the app folder so its import name matches what your MicroPython code imports. For Breakout, the `xtensawin` build is named `breakout.mpy` inside the app folder.
73+
4. Build the `.mpk` normally. The native `.mpy` is packaged alongside the Python files.
74+
75+
```
76+
com.micropythonos.breakout/
77+
├── MANIFEST.JSON
78+
├── icon_64x64.png
79+
├── main.py
80+
└── breakout.mpy # native module, imported by main.py
81+
```
82+
83+
## Limitations
84+
85+
- Native modules must be compiled separately for each target architecture (for example, `x64` for desktop and `xtensawin` for ESP32).
86+
- The MicroPython natmod ABI can change between releases, so rebuild modules when the `lvgl_micropython` submodule is updated.
87+
- Native code has the same filesystem and memory constraints as the rest of the app.
88+
89+
## See also
90+
91+
- [Bundling Apps](bundling-apps.md) — packaging apps as `.mpk` files
92+
- [MicroPython Native Module Documentation](https://docs.micropython.org/en/latest/develop/natmod.html)
93+
- [Creating Apps](creating-apps.md) — writing an app from scratch

docs/frameworks/audiomanager.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,27 @@ AudioManager.record_wav_adc(
121121
)
122122
```
123123

124+
### Desktop WAV Playback
125+
126+
On Linux and macOS desktop builds, WAV playback uses an external audio player subprocess instead of I2S hardware. `AudioManager` automatically detects one of the following players in order of preference:
127+
128+
1. `ffplay` (FFmpeg)
129+
2. `aplay` (ALSA)
130+
3. `paplay` (PulseAudio)
131+
4. `afplay` (macOS)
132+
133+
If none is installed, the player still runs in "timing simulation" mode so apps can test playback flow without sound.
134+
135+
```bash
136+
# Ubuntu/Debian
137+
sudo apt install ffmpeg
138+
139+
# macOS
140+
# afplay is pre-installed
141+
```
142+
143+
Priority and volume controls apply conceptually on desktop, although the external player handles the actual output.
144+
124145
## Audio Focus Priority
125146

126147
AudioManager implements a 3-tier priority-based audio focus system inspired by Android:
@@ -240,7 +261,7 @@ Set or get the global volume (0–100).
240261
| **Fri3d 2024 Badge** ||||| Full audio support |
241262
| **Fri3d 2026 Badge** ||||| ADC mic via `adc_mic` |
242263
| **Waveshare ESP32-S3** ||||| I2S output only |
243-
| **Linux/macOS** | | ✅ (simulated) | ✅ (simulated) || Simulated recording for testing |
264+
| **Linux/macOS** | ✅ (external player) | ✅ (simulated) | ✅ (simulated) || WAV playback via `ffplay`/`aplay`/`paplay`/`afplay` |
244265

245266
## Troubleshooting
246267

docs/frameworks/file-explorer-activity.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ The system then resolves the file to the appropriate viewer using the manifest-d
9999

100100
Long-pressing a file or folder opens an action bar with **Delete**, **Rename**, and **Cancel** options. Delete shows a confirmation dialog; Rename launches `RenameActivity`.
101101

102+
### Deleting directories
103+
104+
Deleting a folder removes it recursively, including all files and subdirectories inside it. A confirmation dialog is shown before any deletion begins.
105+
106+
!!! warning
107+
Directory deletion cannot be undone. Use the confirmation dialog carefully, especially when deleting paths under `/data/` or `/apps/`.
108+
102109
## Example: image picker
103110

104111
```python

docs/frameworks/focus.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ if focusgroup:
4444

4545
`add_focus_border` only draws the visual feedback; it does **not** add the widget to the focus group.
4646

47+
### Touch-aware behavior
48+
49+
On devices that are primarily controlled with a touchscreen, the focus border is intentionally hidden until the user first navigates with a directional input (keyboard, hardware buttons, or a rotary encoder). This keeps touch-only screens clean while still making focused elements obvious once physical navigation begins.
50+
51+
If you want a widget to reveal the focus border immediately, ensure it is added to the default focus group and focus it programmatically:
52+
53+
```python
54+
focusgroup = lv.group_get_default()
55+
if focusgroup:
56+
focusgroup.add_obj(btn)
57+
focusgroup.focus_obj(btn)
58+
```
59+
4760
## Examples
4861

4962
### Basic usage

docs/frameworks/font-manager.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ Return a font object suitable for use with `set_style_text_font()`.
9191

9292
**Returns:** `lv.font_t` — the requested font, possibly wrapped with emoji support.
9393

94+
If the requested `family` is not available, FontManager falls back to Montserrat, then to the first available built-in font, and finally to `lv.font_montserrat_12`.
95+
9496
**Example:**
9597

9698
```python
@@ -202,6 +204,10 @@ builtin/res/emojis/
202204

203205
Files are named by their Unicode codepoint(s) in uppercase hex, with multiple codepoints joined by `-` (e.g. `1F600.png` for 😀, `1F3CE-FE0F.png` for 🏎️, `1F1F8-1F1FB.png` for 🇸🇻). FontManager scans the directory at runtime and builds a `{codepoint: path}` map.
204206

207+
### Missing emoji fallback
208+
209+
If the exact PNG for an emoji is not bundled, FontManager tries visually similar emoji before giving up. For example, several kissing-face variants can substitute for each other. This keeps text readable even when only a small emoji set is included in the firmware.
210+
205211
### Adding new emoji
206212

207213
1. Add a PNG named `<CODEPOINT_HEX>.png` to `32x32/`:

docs/frameworks/notification-manager.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,29 @@ Notification.PRIORITY_MAX = 3
6363

6464
The drawer sorts notifications by priority, then by most recent update time.
6565

66+
## Notification sounds
67+
68+
When a new notification arrives, the system can play a short RTTTL ringtone on the device's buzzer output. The sound is stored as an RTTTL string in the Settings app's `SharedPreferences` under the key `notification_sound`.
69+
70+
Available sounds:
71+
72+
| Label | RTTTL string |
73+
|-------|--------------|
74+
| `None` | (empty string, no sound) |
75+
| `Coin` | `coin:d=8,o=6,b=200:16b5,e6` |
76+
| `Scale up` | `scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b` |
77+
| `Superhappy` | `superhappy:d=8,o=5,b=635:c,e,g,c,e,g,c,e,g,c6,e6,g6,c6,e6,g6,c7,e7,g7,c7,e7,g7,c7,e7,g7` |
78+
79+
The default sound is `Coin`. If no buzzer output is available, the notification posts silently. Apps can change the sound programmatically:
80+
81+
```python
82+
from mpos import SharedPreferences
83+
84+
prefs = SharedPreferences("com.micropythonos.settings")
85+
prefs.put_string("notification_sound", "coin:d=8,o=6,b=200:16b5,e6")
86+
prefs.commit()
87+
```
88+
6689
## NotificationManager API
6790

6891
All methods are class methods. `NotificationManager` initializes itself lazily on first use.

0 commit comments

Comments
 (0)