059b705a38
fix: webserver: Use streaming response for filesystem listing
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m37s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-20 19:26:18 +01:00
3213ec8f66
feat: webserver: set and delete playlists
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-20 19:26:16 +01:00
e2ca9e5139
feat: api endpoint to get playlist properties
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m36s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Failing after 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 7s
Run pytests / Check-Pytest (push) Successful in 10s
2025-12-20 16:52:37 +01:00
070cf887ab
feat(wip): api endpoint to get playlist properties
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m47s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Failing after 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 7s
Run pytests / Check-Pytest (push) Successful in 10s
2025-12-20 15:40:52 +01:00
28846c9274
wip: api endpoint to list all available audio files
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m37s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Failing after 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
Iterative approach. Currently only lists mp3 files.
2025-12-20 14:40:07 +01:00
51cb2c3a68
feat: api endpoint for reading all available playlists
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m36s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Failing after 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
2025-12-19 18:33:42 +01:00
32bf6a8d68
always return content type application/json
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m36s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
2025-12-16 23:13:04 +01:00
e2f9287ebd
feat: last connected tag uid available at /api/v1/last_tag_uid
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m39s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
2025-12-16 22:41:55 +01:00
19dff763bd
feat: webserver: keep alive; move playback write prot to handler
...
- Reset the app idle timer when interacting with the webapp, so that the
device does not turn off while the web ui is used.
- Handle denying put/post while playback is active centrally in the
before_request handler, so that it does not need to be copy/pasted
into every request handler.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-16 22:34:06 +01:00
e0ff9c54bc
refactor: timer: split out two helpers from _timer_worker
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m35s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-16 20:19:30 +01:00
c0b9ef2961
fix: timer: handle modifications to timers when _timer_worker is already scheduled correctly
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m45s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 12s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-07 13:25:35 +01:00
e23f8bd34c
fix: exceptions in callback should not terminate caller
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m46s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-07 13:09:34 +01:00
97e9742c75
feat: Add basic watchdog timer
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-07 13:09:34 +01:00
aa1a02ce54
feat: copy build unix executable to other build artifacts
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m45s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 8s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 12s
2025-12-03 21:00:26 +01:00
96759c999c
fix: Block certain requests during playback
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m42s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 12s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 7s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
Probably due to memory/stack overrun, some more involved web API
requests cause the system to hang if performed during playback. For now,
block these requests during playback.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-03 20:36:41 +01:00
a7e58853bb
feat: Add api/v1/config to get, put config
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m40s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 12s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 12s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-03 20:12:29 +01:00
2e1bc7782b
fix: Ensure each timer can only be scheduled once
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m58s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s
Run pytests / Check-Pytest (push) Successful in 13s
If a timer is scheduled with the timer manager while it is already
scheduled, the new exipry time should override the prev. expiry time
instead of adding a second instance of the same timer function.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
fa0e23ee87
feat: Add play/pause and prev track function
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
856bf34161
feat: Make button mapping configurable
...
- Remove Pin to button mapping from hwconfig, replace with a simple list
of Pins to which buttons are attached
- Add BUTTON_MAP to config.json which maps indices in the HW button list
to button names
- Update utils.Buttons to use the button map to connect the correct pins
to the matching key codes
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
83deb1b4c2
feat: Replace hardcoded timeouts in app with configurable
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
2225906664
feat: Move LED_COUNT from hwconfig to config.json
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
176fc66c17
feat: config store
...
Load a config.json file from the root of the littlefs flash filesystem.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-12-01 20:25:30 +01:00
3c23fc1446
feat: freeze all python code, restructure build
...
Add all python code run on the device to the manifest.py to freeze
it. This has two benefits:
- It precompiles the bytecode, so it is smaller and faster
- All code (C and python) is now in the firmware image, leaving the
littlefs filesystem on the flash free for user settings.
This requires changing the way the hardware variants are handled. There
is now only one _filesystem_ image, but instead there are different
_firmware_ images for each variant.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-28 18:19:50 +01:00
111ae65ebc
cleanup: Remove unused python files from src
...
Remove python files that are not referenced directly or indirectly by
main.py.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-28 17:59:13 +01:00
e07ee46518
style: Fix flake8 complaints
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m28s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
Remove unused imports in main.py
Add missing "global" in webserver and fix spacing.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-28 17:48:39 +01:00
cd5515ddad
feat: new micropython variant with support for microdot
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m36s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Failing after 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 12s
2025-11-11 22:32:00 +01:00
99ad8582f0
Defined the two endpoints we need for webapi version 1
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m28s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Failing after 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
2025-11-11 22:30:23 +01:00
ae875950cd
Enabled --update flag for differential flashing
2025-11-11 22:30:23 +01:00
340aea6be6
Factored out webserver sample into dedicated module
2025-11-11 22:30:18 +01:00
f64bbc27fd
basic webserver works
2025-11-11 22:28:55 +01:00
abb880baca
print network interface info
2025-11-11 22:28:49 +01:00
a59f00ad60
disabled wifi power management for now
2025-11-11 22:26:04 +01:00
135ad11de9
Minimal example for api endpoint
2025-11-11 22:26:04 +01:00
ff52e989a2
Forumlated potentially useful json schema.
...
Note that this is based on an earlier state of the project, and the
terms used in this schema may differ from the current state of the project.
2025-11-11 22:26:04 +01:00
869a92d998
feat: Implement shutdown on idle when on battery
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m24s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Allow the PlayerApp to turn off the device if it is idle for longer then
the timeout. The timeout is currently hardcoded to 1 minute, this will be
made configurable in the future.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-11 20:31:48 +01:00
696f7b956c
feat: Change LED pattern based on playback state
...
Move the LED control to the utils.LedManager class. For the first
implementation, support two LED patterns 'idle' and 'playing'.
Extend the PlayerApp to set the LED pattern based on playback state.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-11 20:30:54 +01:00
595f3bd37f
fix(db): Fix type check in BTreeDB.getSetting
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m30s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
Fix missing type() call in type check.
Also remove leftover debug print().
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-09 16:33:33 +01:00
7d3cdbabe4
feat(app): Implement tag handling modes according to #28 .
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m24s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 6s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
If the tagmode setting is 'tagremains' (the default): Play as long as the
tag is on the reader, with a 5 second timeout (i.e. playback stops when
tag is gone for more than 5 seconds).
If the tagmode setting is 'tagstartstop': Playback starts when a tag is
seen. Presenting a different tag causes the playback to stop and
playback for the new tag to start. Re-presenting the same tag used to
start with a no-tag-time of 5 seconds or more in between stops playback.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-04 19:25:10 +01:00
b5e3df1054
refactor(app): Refactor tag handling
...
Split the tag handling in PlayerApp into two parts: The low level
handling of changed/removed tags from the Nfc reader, including the
timeout processing is moved into the nested TagStateMachine class. The
main PlayerApp has two new (internal) callbacks "onNewTag" and
"onTagRemoved" which are called when a new tag is presented or a tag was
actually removed. This will hopefully make the implementation of #28
"Configurable Tag Handling" cleaner.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-04 19:25:10 +01:00
55718aa1ff
Merge pull request '24-playlist-modes' ( #46 ) from 24-playlist-modes into main
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m23s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 11s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 9s
Run pytests / Check-Pytest (push) Successful in 11s
Reviewed-on: #46
Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de >
2025-11-04 18:23:57 +00:00
b56e4f36b4
fix(main): Make upgrade from tag directories more ergonomical
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m21s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
As we don't have an API to upload files and create playlists yet, we
used the convention "tag uid as directory name" to allow testing
playback. With the introduction of the database in #39 "Add playlist db"
a builddb() function to initialize the database from the tag directories
was added, but it is not automatically called. To make the developer
experience more ergonomical, add a check for that automatically runs
builddb() when no database exists.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-11-02 18:06:18 +01:00
db136ed79a
Wifi setup function with initial wlan config and per-board unique ssid
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m21s
Check code formatting / Check-C-Format (push) Successful in 9s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
2025-11-02 17:21:48 +01:00
6a9ff9eb0a
playlistdb: Implement shuffle
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m22s
Check code formatting / Check-C-Format (push) Successful in 8s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Initial implementation of shuffle with a naive algorithm.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-10-31 14:21:35 +01:00
7327549eea
refactor(playlistdb): Enforce constant entry index length
...
To simplify the playlist handling, enforce that the indices are always
formatted to the same length (5, which allows for 100000 entries, that
should be enough).
Then make the position stored in the Playlist object be a simple integer
instead of a database key. This simplifies the code, and will make
implementing shuffle much easier.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-10-31 14:21:35 +01:00
7e532ec641
app, mp3player: Hook up playlists 'offset' persist mode
...
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-10-31 14:21:35 +01:00
5013e2359d
playlistdb: Add shuffle and persist settings
...
Add documentation of playlist database schema in DEVELOP.md.
Add settings for persist and shuffle to BTreeDB. Implement the different
persist modes. Shuffle will be implemented in a followup commit.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-10-31 14:21:35 +01:00
4512b91763
Merge PR #42 from remote-tracking branch 'origin/fix-sd-spi-hwconfig' into main
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m23s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 9s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
Reviewed-on: #42
Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de >
2025-10-31 14:19:27 +01:00
a81952fb8a
Merge pull request 'fix-interrupt-race' ( #45 ) from fix-interrupt-race into main
...
Check code formatting / Check-C-Format (push) Has been cancelled
Build RPi Pico firmware image / Build-Firmware (push) Has been cancelled
Check code formatting / Check-Python-Flake8 (push) Has been cancelled
Check code formatting / Check-Bash-Shellcheck (push) Has been cancelled
Run unit tests on host / Run-Unit-Tests (push) Has been cancelled
Run pytests / Check-Pytest (push) Has been cancelled
Reviewed-on: #45
Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de >
2025-10-30 16:52:25 +00:00
92f9ce3d5a
Merge pull request 'Add playlist database' ( #39 ) from 23-add-playlist-db into main
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m23s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 11s
Reviewed-on: #39
Reviewed-by: Stefan Kratochwil <kratochwil-la@gmx.de >
2025-10-27 20:37:49 +00:00
23d5b050dc
audiocore: Fix race window in i2s_stop
...
Build RPi Pico firmware image / Build-Firmware (push) Successful in 3m23s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 4s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
Apply the same pattern as in 6f155ebb55 ("audiocore: Fix small race
window in get_fifo_read_value_blocking") and 2a4033d3ca ("rp2_sd: Fix
race window in sd_spi_wait_complete") to the wait for interrupt in
i2s_stop too.
Signed-off-by: Matthias Blankertz <matthias@blankertz.org >
2025-10-27 21:25:52 +01:00